Woocommerce modifying the html on the checkout page?

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

Topic woocommerce-offtopic Wordpress

Category Web


I am using Bootstrap 4.x. So I wanted to change the structure too. What I have done is the following:

In woocommerce/templates/checkout/form-billing.php I can target all fields separately, by calling:

<div class="row">
    <div class="col-6">
       <?php woocommerce_form_field('billing_first_name', array('placeholder' => 'Vorname *', 'required' => true), $checkout->get_value('billing_first_name')); ?>
    </div>
    <div class="col-6">
       <?php woocommerce_form_field('billing_last_name', array('placeholder' => 'Nachname *', 'required' => true), $checkout->get_value('billing_last_name')); ?>
    </div>
</div>

The output is inserted inside of <p class="form-row form-row-first validate-required" id="billing_<name-of-field>_field">, because it is predefined in: plugins/woocommerce/includes/wc-template-functions.php on line 2692. So there is no way to alter that, because it is hardcoded in the template function. You can write your own form field in plain HTML instead, check the HTML-Output of woocommerce_form_field();

@the_lar: Thank you for your information: Thank you for pointing out that there is a problem with the country field, I've run into this annoying bug. If you check the file, there is on line 141 the following code: rows.detach().appendTo( wrapper );. If you check line 114 you will see that rows points to .form-row, which is hardcoded in wc-template-functions.php.


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;
}

About

Geeks Mental is a community that publishes articles and tutorials about Web, Android, Data Science, new techniques and Linux security.