14

I was previously using this answer to hide checkout fields based on chosen shipping method, it worked fine until an update (3.4.2 current version) I think not sure what has changed but it doesn't work as intended anymore.

Previously when local pickup was chosen some fields were hidden and made optional and when delivery was chosen it would show those fields again all via dynamically without reloading the page.

Now it shows and hides the fields as required however, when delivery is chosen it is showing the correct fields marked as mandatory but also has the (optional) sign next to it and it makes it optional. See picture below.

enter image description here

Here's my modified snipper below:

add_filter('woocommerce_default_address_fields', 'custom_default_checkout_fields', 10, 1 );
function custom_default_checkout_fields( $address_fields ) {
$custom_fields = array( 'country', 'address_1', 'address_2', 'state', 'postcode');
foreach($custom_fields as $field)
    $address_fields[$field]['required'] = false;
return $address_fields;
}

add_action( 'wp_footer', 'custom_checkout_field_script' );
function custom_checkout_field_script() {

$pickpoint = 'local_pickup:2';
$free_delivery = 'free_shipping:1';
$flat_rate = 'flat_rate:3';

$required = esc_attr__( 'required', 'woocommerce' );
?>
<script>
    jQuery(function($){

        var shippingMethod = $('input[name^="shipping_method"]:checked'),
            required = '<abbr class="required" title="<?php echo $required; ?>">*</abbr>',
            shippingChecked = $('input#ship-to-different-address-checkbox');

        shippingChecked.change( function(){
            console.log('Shipping Checked: '+shippingChecked.prop('checked'));
        });

        function showHide( actionToDo='show', selector='' ){
            if( actionToDo == 'show' )
                $(selector).show(function(){
                    $(this).addClass("validate-required");
                    $(this).removeClass("woocommerce-validated");
                    $(this).removeClass("woocommerce-invalid woocommerce-invalid-required-field");
                    if( $(selector+' > label > abbr').html() == undefined )
                        $(selector+' label').append(required);
                });
            else
                $(selector).hide(function(){
                    $(this).removeClass("validate-required");
                    $(this).removeClass("woocommerce-validated");
                    $(this).removeClass("woocommerce-invalid woocommerce-invalid-required-field");
                    if( $(selector+' > label > abbr').html() != undefined )
                        $(selector+' label > .required').remove();
                });
        }

        if( shippingMethod.val() == '<?php echo $pickpoint; ?>' )
        {
            showHide('show','#billing_country_field' );
            showHide('hide','#billing_address_1_field' );
            showHide('hide','#billing_address_2_field' );
            showHide('hide','#billing_postcode_field' );
            showHide('hide','#billing_state_field' );
        }
        else if( shippingMethod.val() == '<?php echo $free_delivery; ?>' || '<?php echo $flat_rate; ?>')
        {
            showHide('show','#billing_address_1_field');
            showHide('show','#billing_address_2_field');
            showHide('show','#billing_postcode_field');
            showHide('hide','#billing_state_field');
            showHide('hide','#billing_country_field');
        }

        $( 'form.checkout' ).on( 'change', 'input[name^="shipping_method"]', function() {
            var shipMethod = $('input[name^="shipping_method"]:checked');
            if( shipMethod.val() == '<?php echo $pickpoint; ?>' )
            {
                showHide('show','#billing_country_field');
                showHide('hide','#billing_address_1_field');
                showHide('hide','#billing_address_2_field');
                showHide('hide','#billing_postcode_field');
                showHide('hide','#billing_state_field');
            }
            else if( shipMethod.val() == '<?php echo $free_delivery; ?>' || '<?php echo $flat_rate; ?>')
            {
                showHide('show','#billing_address_1_field');
                showHide('show','#billing_address_2_field');
               showHide('show','#billing_postcode_field');
                showHide('hide','#billing_state_field');
                showHide('hide','#billing_country_field');
            }
            else
            {
                showHide('show','#billing_address_1_field');
                showHide('show','#billing_address_2_field');
                showHide('show','#billing_postcode_field');
                showHide('show','#billing_state_field');
                showHide('show','#billing_country_field');
            }
        });

        $( 'input#ship-to-different-address-checkbox' ).click( function() {
            var shipMethod = $('input[name^="shipping_method"]:checked');
            if( shipMethod.val() == '<?php echo $pickpoint; ?>' && shippingChecked.prop('checked') == true )
            {
                showHide('show','#billing_country_field');
                showHide('hide','#billing_address_1_field');
                showHide('hide','#billing_address_2_field');
                showHide('hide','#billing_postcode_field');
                showHide('hide','#billing_state_field');

                showHide('show','#shipping_country_field');
                showHide('hide','#shipping_address_1_field');
                showHide('hide','#shipping_address_2_field');
                showHide('hide','#shipping_postcode_field');
                showHide('hide','#shipping_state_field');
            }
            else if( shipMethod.val() == '<?php echo $free_delivery; ?>' || '<?php echo $flat_rate; ?>' && shippingChecked.prop('checked') == true )
            {
                showHide('show','#billing_address_1_field');
                showHide('show','#billing_address_2_field');
                showHide('show','#billing_postcode_field');
                showHide('hide','#billing_state_field');
                showHide('hide','#billing_country_field');

                showHide('show','#shipping_address_1_field');
                showHide('show','#shipping_address_2_field');
                showHide('show','#shipping_postcode_field');
                showHide('hide','#shipping_state_field');
                showHide('hide','#shipping_country_field');
            }
            else if( shippingChecked.prop('checked') == false )
            {
                showHide('show','#shipping_address_1_field');
                showHide('show','#shipping_address_2_field');
                showHide('hide','#shipping_state_field');
                showHide('hide','#shipping_country_field');
            }
        });
    });
</script>
<?php
}

Any pointers would be much appreciated!

Daniel Widdis
  • 8,424
  • 13
  • 41
  • 63
Abu Nooh
  • 846
  • 4
  • 12
  • 42

3 Answers3

13

you can easily use css in this

.woocommerce form .form-row .required{
    display: none ;
}

.woocommerce form .form-row .optional{
    display: none ;
}
Walter Mirwoba
  • 155
  • 1
  • 2
  • 1
    Using CSS to remove elements permanently is not a very good solution in my opinion … but better than a JS solution like in the accepted answer – GDY Mar 05 '19 at 07:53
  • This worked great for me! I'm curious about why @GDY noted using CSS is not a good solution. Just want to make sure I'm using the best approach. – jord8on Dec 13 '19 at 18:34
  • 4
    @jord8on: It's bad style, if you want to remove something then really remove it and don't make it just invisible. You can think of "cleaning up your room" and just putting the stuff under your bed :D … But in such enviroments it's often the most convenient and viable solution, so definitely usable. But i would always prefer to really remove such elements if that is an option. – GDY Jan 03 '20 at 09:07
  • @gdy: Great insight! Thanks for sharing. I always like to know the WHY! – jord8on Jan 04 '20 at 15:27
  • 2
    @GDY for this situation, hiding the text "Optional" with CSS is fine, it seems to me. Very small overhead and can easily be reversed. In many cases I would agree; it's better to remove something altogether, especially if it's something that consumes a significant amount of resources to create in the first place. – MQuiggGeorgia May 23 '20 at 20:03
  • @MQuiggGeorgia Yeah as mentioned this is fine as it is :). Especially in systems like WC hooks are changing more often than classes which may make this even more robust and also better to maintain because you don't have to dive into the systems architecture if anything changes … just adjust the class. On the other hand this may lead to abandonned styles and some other problems … especially if you do a lot of adjustments like this. In this specific case i would probably prefer a class based approach too. I just wanted to point out that this is not the cleanest way of doing this ;) – GDY Jun 15 '20 at 14:02
12

Update 2

To remove "(optional)" text from checkout fields labels introduced with Woocommerce release 3.4, just as it was before, you will need to add the following code:

// PHP: Remove "(optional)" from our non required fields
add_filter( 'woocommerce_form_field' , 'remove_checkout_optional_fields_label', 10, 4 );
function remove_checkout_optional_fields_label( $field, $key, $args, $value ) {
    // Only on checkout page
    if( is_checkout() && ! is_wc_endpoint_url() ) {
        $optional = '&nbsp;<span class="optional">(' . esc_html__( 'optional', 'woocommerce' ) . ')</span>';
        $field = str_replace( $optional, '', $field );
    }
    return $field;
}

// JQuery: Needed for checkout fields to Remove "(optional)" from our non required fields
add_filter( 'wp_footer' , 'remove_checkout_optional_fields_label_script' );
function remove_checkout_optional_fields_label_script() {
    // Only on checkout page
    if( ! ( is_checkout() && ! is_wc_endpoint_url() ) ) return;

    $optional = '&nbsp;<span class="optional">(' . esc_html__( 'optional', 'woocommerce' ) . ')</span>';
    ?>
    <script>
    jQuery(function($){
        // On "update" checkout form event
        $(document.body).on('update_checkout', function(){
            $('#billing_country_field label > .optional').remove();
            $('#billing_address_1_field label > .optional').remove();
            $('#billing_postcode_field label > .optional').remove();
            $('#billing_state_field label > .optional').remove();
            $('#shipping_country_field label > .optional').remove();
            $('#shipping_address_1_field label > .optional').remove();
            $('#shipping_postcode_field label > .optional').remove();
            $('#shipping_state_field label > .optional').remove();
        });
    });
    </script>
    <?php
}

Code goes in function.php file of your active child theme (or active theme). Tested and works in Woocommerce version 3.4+.

You could merge the included jQuery code with your existing jQuery code…

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
  • @LoicTheAztec thank you for updating it, as it is, it makes the fields optional without actually hiding any of the fields. Regardless of which method is chosen. Any option including delivery makes the fields optional. – Abu Nooh Jun 09 '18 at 13:37
  • @AbuNooh Sorry this was quiet complicated, a real nightmare in checkout page. But finally I have found the correct combination to make it work. – LoicTheAztec Jun 10 '18 at 18:59
  • Loic, no need to apologise and thank you for taking the time to have a look. It works but there is one little issue, in the fact that it removes to optional lable but still treats those fields as optional, so one could pass validation without filling in the address, postcode and state fields. I'm not entirely sure how to go about making them required again. I think `$address_fields[$field]['required'] = false;` needs to be undone somehow. Thanks again! – Abu Nooh Jun 10 '18 at 21:58
  • I'm back Loic, why does it do this? https://imgur.com/a/UbuCu2m even though the fields are present and marked as mandatory? Is it happening for you? – Abu Nooh Jun 11 '18 at 19:53
  • Is there any way to make this work when the option `hide shipping methods until an address is entered` is checked because the `shipping checked: false` disables the AJAX for some reason. – Abu Nooh Aug 28 '18 at 13:03
6

A better solution:

/**
 * Remove optional label
 * https://elextensions.com/knowledge-base/remove-optional-text-woocommerce-checkout-fields/
 */
add_filter( 'woocommerce_form_field' , 'elex_remove_checkout_optional_text', 10, 4 );
function elex_remove_checkout_optional_text( $field, $key, $args, $value ) {
    if( is_checkout() && ! is_wc_endpoint_url() ) {
        $optional = '&nbsp;<span class="optional">(' . esc_html__( 'optional', 'woocommerce' ) . ')</span>';
        $field = str_replace( $optional, '', $field );
    }
    return $field;
}
Bogdan
  • 342
  • 5
  • 13