There is no hook woocommerce_form_field
, there is hook woocommerce_form_field_{$args[type]}
(doc).
$args[type]
can be (look here for available options):
- text,
- checkbox,
- country,
- …
Code below will wrap ‘billing_first_name‘ and ‘billing_last_name‘ fields in a wrapper like <div class="first-and-second-field-wrapper"> [...] </div>
.
function change_woocommerce_field_markup($field, $key, $args, $value) {
$field = '<div class="single-field-wrapper">'.$field.'</div>';
if($key === 'billing_first_name')
$field = '<div class="first-and-second-field-wrapper">'.$field;
else if ($key === 'billing_last_name')
$field = $field.'</div>';
return $field;
}
add_filter("woocommerce_form_field_text","change_woocommerce_field_markup", 10, 4);
It will also wrap text
type fields with <div class="single-field-wrapper">...</div>
.
BUT
some text fields that have own type (like state or email) require additional hooks, for example:
add_filter("woocommerce_form_field_country","change_woocommerce_field_markup", 10, 4);
add_filter("woocommerce_form_field_email","change_woocommerce_field_markup", 10, 4);
UPDATE #1
Above code works in WC-v3.3.7.
In WC-v3.4.xx you get this:
<div class="first-and-second-field-wrapper">
<div class="single-field-wrapper">
<div class="single-field-wrapper">
[here there are all the fields, one under the other ]
</div>
<div class="single-field-wrapper"></div>
<div class="single-field-wrapper"></div>
<div class="single-field-wrapper"></div>
....
<div class="single-field-wrapper"></div>
</div>
because javascript sorts form rows inside .woocommerce-billing-fields__field-wrapper
. Look at the file woocommerce/assets/js/frontend/address-i18n.js
, from line 99.
JS finds all HTML tags with “.form-row” class inside wrapper, takes parent of first item (tag with class .form-row
), sort items by priority and insert them into previously selected parent element.
For the test, change in file address-i18.js
, in line 99
var fieldsets = $('.woocommerce-billing-fields__field-wrapper, ...
to
var fieldsets = $('.woocommerce-billing-fields__field-wrapper2, ...
and upload as address-i18.min.js
.
Removing JS sorting is not a solution, it is just a test. Whithout sorting by JS you will get this:
<div class="first-and-second-field-wrapper">
<div class="single-field-wrapper">
<p class="form-row ..." id="billing_first_name_field"> <label for="billing_first_name"> ... </p>
</div>
<div class="single-field-wrapper">
<p class="form-row ..." id="billing_last_name_field"> <label for="billing_last_name">... </p>
</div>
</div>
<div class="single-field-wrapper">
<p class="form-row ..." id="billing_company_field"> <label for="billing_company">... </p>
</div>