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:
- Filter by type: here we can specify the
$args['type']
liketext
,password
,datetime
,select
,radio
, etc...
/**
* Filter by type.
*/
$field = apply_filters( 'woocommerce_form_field_' . $args['type'], $field, $key, $args, $value );
- 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
Can't Install PHPunit via Pear, Requires Pear Installer >= 1.9.2, Can't Upgrade Pear from 1.9.0
Invalid JSON Parsing Using PHP
Proper Repository Pattern Design in PHP
PHP Sessions in a Load Balancing Cluster - How
How to Render Zf2 View Within JSON Response
What Literal Characters Should Be Escaped in a Regex
How to Use Composer Packages in Codeigniter
PHP Get Request, Sending Headers
How to Explain the Result for a New \Datetime('0000-00-00 00:00:00')
Rest API Authorization & Authentication (Web + Mobile)
Laravel Advanced Wheres How to Pass Variable into Function
Accessing an Associative Array by Integer Index in PHP
PHP Multidimensional Array Get Values
Remotely Destroy a Session in PHP (User Logs in Somewhere Else)