How to Change the Woocommerce_Form_Field HTML Structure

How should I change the woocommerce_form_field HTML Structure?

To rewrite the output html from the woocommerce_form_field function there are 2 filter hooks available:

  1. Filter by type: here we can specify the $args['type'] like text, password, datetime, select, radio, etc...
/**
* Filter by type.
*/
$field = apply_filters( 'woocommerce_form_field_' . $args['type'], $field, $key, $args, $value );

  1. General filter on form fields: a general filter where we can then add an if condition to apply this to a specific type of field
/**
* General filter on form fields.
*
* @since 3.4.0
*/
$field = apply_filters( 'woocommerce_form_field', $field, $key, $args, $value );

The first option seems most suitable for your question

So

apply_filters( 'woocommerce_form_field_' . $args['type']...

Is going to be ( Where $args['type'] is equal to radio )

function filter_woocommerce_form_field_radio( $field, $key, $args, $value ) {
// Do something
return $field;
}
add_filter( 'woocommerce_form_field_radio', 'filter_woocommerce_form_field_radio', 10, 4 );

The callback function uses $field which contains all HTML from <p> to the closing </p> HTML tag, so we have the ability to rewrite the entire output of this through our function


Source used for this answer: wc-template-functions.php#L2847-L2850, note the use of $args with which the code can be dynamically constructed.

(This code was copied from wc-template-functions.php line 2847 - 2850)

foreach ( $args['options'] as $option_key => $option_text ) {
$field .= '<input type="radio" class="input-radio ' . esc_attr( implode( ' ', $args['input_class'] ) ) . '" value="' . esc_attr( $option_key ) . '" name="' . esc_attr( $key ) . '" ' . implode( ' ', $custom_attributes ) . ' id="' . esc_attr( $args['id'] ) . '_' . esc_attr( $option_key ) . '"' . checked( $value, $option_key, false ) . ' />';
$field .= '<label for="' . esc_attr( $args['id'] ) . '_' . esc_attr( $option_key ) . '" class="radio ' . implode( ' ', $args['label_class'] ) . '">' . esc_html( $option_text ) . '</label>';
}

So to answer your question: We get, based on the $key so that it is applied only for that specific piece

function filter_woocommerce_form_field_radio( $field, $key, $args, $value ) {
// Based on key
if ( $key == 'radio_choice' ) {
if ( ! empty( $args['options'] ) ) {

$field = '<div><ul>';

foreach ( $args['options'] as $option_key => $option_text ) {
$field .= '<li>';
$field .= '<input type="radio" value="' . esc_attr( $option_key ) . '" name="' . esc_attr( $key ) . '" id="' . esc_attr( $args['id'] ) . '_' . esc_attr( $option_key ) . '" />';
$field .= '<label>' . esc_html( $option_text ) . '</label>';
$field .= '</li>';
}

$field .= '</ul></div>';
}
}

return $field;
}
add_filter( 'woocommerce_form_field_radio', 'filter_woocommerce_form_field_radio', 10, 4 );

Output:

<div>
<ul>
<li>
<input type="radio" value="0" name="radio_choice" id="radio_choice_0">
<label>No Option</label>
</li>
<li>
<input type="radio" value="10" name="radio_choice" id="radio_choice_10">
<label>Option 1 ($10)</label>
</li>
<li>
<input type="radio" value="30" name="radio_choice" id="radio_choice_30">
<label>Option 2 ($30)</label>
</li>
</ul>
</div>

How to rearrange/customize html in woocommerce checkout form fields

For the first one you can do the following to display single input field

<?php 

woocommerce_form_field(
"billing_first_name",
$checkout->checkout_fields['billing']['billing_first_name'],
$checkout->get_value( 'billing_first_name' )
);

?>

where you can replace first_name with any key of the checkout billing fields

So for your example it will be something like this

<h3>my custom heading</h3>

<p class="form-row form-row validate-required">

<?php woocommerce_form_field( "billing_email", $checkout->checkout_fields['billing']['billing_email'], $checkout->get_value( 'billing_email' ) ); ?>

</p>

As for the second I'm not sure how you can achieve that. I needed something similar and i used javascript to reposition the labels.

something like :

jQuery('form.checkout label').each(function(){
jQuery(this).insertAfter(jQuery(this).parent().find('input'));
})

How do I add HTML to the billing_email field at WooCommerce checkout?

To make a change specifically and only for the billing_email field, you can use the 'woocommerce_form_field_' . $args['type'], filter hook. Where $args['type'] can be replaced with type email

$field contains all HTML from <p> to the closing </p>. However, because you want to add new HTML between the existing code, instead of rewriting the entire field, you can use str_replace

So you get:

function filter_woocommerce_form_field_email( $field, $key, $args, $value ) {   
// Billing email
if ( $key === 'billing_email') {
// Replace existing html with new ones
$field = str_replace( '</span>', '</span><br><span>Please enter the correct email address so that you can receive our emails.</span>', $field );
}

return $field;
}
add_filter( 'woocommerce_form_field_email', 'filter_woocommerce_form_field_email', 10, 4 );

Related:

  • How should I change the woocommerce_form_field HTML Structure?
  • WooCommerce: Change HTML structure of billing fields in checkout
  • How to add HTML5 'required' attribute to woocommerce_form_field

Woocommerce: hook to move the ‘field description’ below the ‘label’?

The form fields in your checkout are being generated by the woocommerce_form_field() function. This has two filters that will let you either filter the fields by type: woocommerce_form_field_{type} Or the fields in general: woocommerce_form_field.

Unfortunately there is no filter that will let you easily rearrange the HTML generated by the woocommerce_form_field() function, so you would have to use one of the above filters and basically rebuild the whole form field by copying the code from the woocommerce_form_field() function and rearrange the part where the $field_html is constructed.

How to add HTML5 'required' attribute to woocommerce_form_field

If you actually want to change <input.. to <input required.. then you can add the woocommerce_form_field_checkbox filter hook.

The fact is that where the HTML code is created

(This code was copied from wc-template-functions.php line 2799)

<input type="' . esc_attr( $args['type'] ) . '" class="input-checkbox ' . esc_attr( implode( ' ', $args['input_class'] ) ) . '" name="' . esc_attr( $key ) . '" id="' . esc_attr( $args['id'] ) . '" value="1" ' . checked( $value, 1, false ) . ' /> ' . $args['label'] . $required . '</label>';

the option exists to add arguments to the existing $args but not extra HTML code to the HTML itself


So if you add the code below to your existing code, you have the option to adjust the HTML output from the $field

  • str_replace - Replace all occurrences of the search string with the replacement string
function filter_woocommerce_form_field_checkbox( $field, $key, $args, $value ) {
// Based on key
if ( $key == 'privacy_policy_reg' ) {
$field = str_replace( '<input', '<input required', $field );
}

return $field;
}
add_filter( 'woocommerce_form_field_checkbox', 'filter_woocommerce_form_field_checkbox', 10, 4 );

Related: How should I change the woocommerce_form_field HTML Structure?

WooCommerce: Change HTML structure of billing fields in checkout

$field contains the complete <p>...</p> output.
So you can completely adjust the output. To keep it dynamic you can use the values ​​from $args


See: https://github.com/woocommerce/woocommerce/blob/master/includes/wc-template-functions.php#L2830 and accompanying code, how to do this

function change_woocommerce_field_markup($field, $key, $args, $value) {
if( $key === 'billing_first_name') {
$field = 'my html';
}
return $field;
}

add_filter("woocommerce_form_field_text","change_woocommerce_field_markup", 10, 4);


Related Topics



Leave a reply



Submit