0

I'm trying to wrap 'some' of the fields of the checkout page in a div and inject some buttons because I am implementing some address validation.

Basically to start with I need a wrapper around company, address line 1, address line 2, town and postcode so I can show/hide them but I can't seem to get anything to work. Here's what I've tried -

In my filters file:

function change_woocommerce_field_markup($field, $key, $args, $value){
    if($key === 'billing_company') {
        $field = '<div class="address-wrapper">'.$field;
    }
    else if ($key === 'billing_postcode') {
        $field = $field.'</div>';
    }
    else {
        $field = $field;
    }
    return $field;
}
add_filter('woocommerce_form_field', '\App\change_woocommerce_field_markup', 10, 4);

So I'm prepending and appending the relevant fields with the html that opens and closes the wrapper. However the resultant HTML looks like this:

<div class="address-wrapper"></div> <p class="form-row form-row-first validate-required" id="billing_first_name_field".... <p class="form-row form-row-last validate-required" id="billing_last_name_field"....

So it's putting the wrapper at the top of the container! I don't get it, what's going on with this?

Thanks Kevin

0

In your case, you don't need to use the filter to inject the wrapper. Just override the checkout template file and put the wrapper at the line you need to. In your question, you want to modify the billing form. So, it should be from this file woocommerce/templates/checkout/form-billing.php. You can inject your wrapper at this line.

If you don't know how to override the WooCommerce template. Please visit this link: https://docs.woocommerce.com/document/template-structure/

UPDATE: code sample.

foreach ( $fields as $key => $field ) {
    $field['return'] = true;
    $before = "";
    $after = "";

    switch ($key) {
        case 'billing_company':
            $before = '<div class="address-wrapper">';
            break;
        case 'billing_postcode':
            $after = '</div>';
            break;      
        default:
            # code...
            break;
    }

    echo $before . woocommerce_form_field( $key, $field, $checkout->get_value( $key ) ) . $after;
}
  • All the fields are outputed by the woocommerce_form_field function though, but I don't want to wrap all of the fields, just a few of them - I don't think your solution will do that will it? – the_lar Sep 27 '19 at 16:04
  • you can do the check condition at the checkout template on foreach loop. – Hồ Trọng Linh Ân Sep 27 '19 at 16:44
  • @the_lar, I also update the code sample on the answer for you. – Hồ Trọng Linh Ân Sep 27 '19 at 16:53
  • Thank you for the code, I really appreciate you trying to help me! I tried it out and I added an inline style to the wrapper so I could see it $before = '<div class="address-wrapper" style="background: red;">'; - so what is happening is that I'm getting a flash of red around the fields, then it gets removed and address-wrapper div is moved up above all the billing fields. There must be some dom manipulation going on? – the_lar Sep 28 '19 at 7:09
  • Hi, after quite a lot of detective work I've tracked this down to the javascript which is in woocommerce/assets/js/frontend/address_i18n.js - this is manipulating the dom in the country_to_state_changing, specifically line 143 where it is detaching the input rows and appending them back to the wrapper! So now I know where this is happening, how would you suggest I alter this behaviour? Obviously I want to do it in a way that won't break when I update woocommerce? – the_lar Sep 28 '19 at 17:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.