Shipping carrier custom fields validation in Wooco

2019-08-06 12:38发布

问题:

I have added two custom input fields in the shipping method section by changing the template /genesis-sample/woocommerce/checkout/review-order.php I have also managed to get them conditionally required. Only when the specific radio button is checked, the input fields appear and become required. I am using jQuery code to make the fields appear and disappear. All of this is working fine. The code is here:

if ( isset($_POST['shipping_method_0_legacy_local_pickup']) && $_POST['shipping_method_0_legacy_local_pickup'] == 1 ) {
    $cheq = 'true';
}
else {
    $cheq = 'false';
}
woocommerce_form_field( 'fieldtester1' , array(
    'type'          => 'text',
    'class'         => array('wccs-field-class wccs-form-row-wide blahblah1'), 
    'label'         => 'Enter Your Carrier Name',
    'required'  => $cheq,
    'placeholder'       => 'Carrier Name',
    ), $checkout->get_value( 'fieldtester1' )); 
woocommerce_form_field( 'fieldtester2' , array(
    'type'          => 'text',
    'class'         => array('wccs-field-class wccs-form-row-wide blahblah2'), 
    'label'         => 'Enter Your Carrier Account #',
    'required'  => $cheq,
    'placeholder'       => 'Carrier Number',
    ), $checkout->get_value( 'fieldtester2' )); 

But here's the problem, even with the required attribute set as true for the two fields, the validation doesn't happen if the field is empty when the Place Order button is pressed. Ideally, the order should not go through and an error message should be generated. I have already added following code in functions.php to force validation of the input field but it doesn't do a thing. The code is here:

add_action('woocommerce_checkout_process', 'carrier_checkout_process');
function carrier_checkout_process() {
    if ( isset($_POST['shipping_method_0_legacy_local_pickup']) && $_POST['shipping_method_0_legacy_local_pickup'] == 1 ) {
        if( empty( $_POST['fieldtester1'] ) ) {
            wc_add_notice( ( "Please don't forget to enter your shipping carrier details." ), "error" );
        }
    }
}

So, here's what I am looking for:

  1. can anyone help me in forcing the validation for two input fields I have added?
  2. After the validation, I would also like to add these two fields in the new order email, and order details in the Wordpress dashboard.

If you are wondering why I am not using a woocommerce checkout field hook to add the input fields in the first place...I am not adding the fields to the checkout form so the hooks aren't of any help. The fields are added in the shipping method section. Another reason was, I wanted to update the required attribute every time a user would switch the shipping method. Using Jquery to change the required attribute wasn't working for whatever reason, believe me I tried for two days. Anyways, that part is already working. The only issues are getting the fields to validate and add them to the order emails and order details. I have looked around everywhere and the closest help I got was this post where LoicTheAztec gave a detailed solution

回答1:

This can be done without jQuery using a special hook that will display your two "Carrier" custom fields below legacy_local_pickup shipping method when it's selected. If customer change to a different shipping method, those fields will be removed.

So you should need to remove your customized template and all related code before.

Now the validation works perfectly and when "Carrier" custom fields are filled, they are saved in order meta data.

// Add custom fields to a specific selected shipping method
add_action( 'woocommerce_after_shipping_rate', 'carrier_custom_fields', 20, 2 );
function carrier_custom_fields( $method, $index ) {
    if( ! is_checkout()) return; // Only on checkout page

    $customer_carrier_method = 'legacy_local_pickup';

    if( $method->id != $customer_carrier_method ) return; // Only display for "local_pickup"

    $chosen_method_id = WC()->session->chosen_shipping_methods[ $index ];

    // If the chosen shipping method is 'legacy_local_pickup' we display
    if($chosen_method_id == $customer_carrier_method ):

    echo '<div class="custom-carrier">';

    woocommerce_form_field( 'carrier_name' , array(
        'type'          => 'text',
        'class'         => array('form-row-wide carrier-name'),
        'label'         => 'Carrier Information:',
        'required'      => true,
        'placeholder'   => 'Carrier Name',
    ), WC()->checkout->get_value( 'carrier_name' ));

    woocommerce_form_field( 'carrier_number' , array(
        'type'          => 'text',
        'class'         => array('form-row-wide carrier-number'),
        'required'      => true,
        'placeholder'   => 'Carrier Number',
    ), WC()->checkout->get_value( 'carrier_number' ));

    echo '</div>';
    endif;
}

// Check custom fields validation
add_action('woocommerce_checkout_process', 'carrier_checkout_process');
function carrier_checkout_process() {
    if( isset( $_POST['carrier_name'] ) && empty( $_POST['carrier_name'] ) )
        wc_add_notice( ( "Please don't forget to enter the shipping carrier name." ), "error" );

    if( isset( $_POST['carrier_number'] ) && empty( $_POST['carrier_number'] ) )
        wc_add_notice( ( "Please don't forget to enter the shipping carrier account number." ), "error" );
}

// Save custom fields to order meta data
add_action( 'woocommerce_checkout_update_order_meta', 'carrier_update_order_meta', 30, 1 );
function carrier_update_order_meta( $order_id ) {
    if( isset( $_POST['carrier_name'] ))
        update_post_meta( $order_id, '_carrier_name', sanitize_text_field( $_POST['carrier_name'] ) );

    if( isset( $_POST['carrier_number'] ))
        update_post_meta( $order_id, '_carrier_number', sanitize_text_field( $_POST['carrier_number'] ) );
}

This code goes on function.php file of your active child theme (or theme). Tested and works.

Not displayed:

Displayed when "Local Pickup" is selected: