Hannah James
Hannah James

Reputation: 570

Show sub Areas dropdown based on chosen city in WooCommerce checkout

I am creating a WooCommerce plugin and I want to display dynamically Sub Areas according to chosen customer city in checkout page.

Here is my code attempt:

add_filter( 'woocommerce_checkout_fields', 'dvs_city_list' );
function dvs_city_list( $fields ) { 
    $fields["billing"]["billing_city"]["type"] = 'select';
    $fields["billing"]["billing_city"]["input_class"] = array(
    'state_select' => 'state_select'
    );  
    $fields["billing"]["billing_city"]["options"] = array(
        'Lahore' => 'Lahore',
        'Karachi' => 'Karachi'
    ),
    return $fields;
}


add_filter( 'woocommerce_checkout_fields', 'dvs_area_list' );
function dvs_area_list( $fields ) { 
    $fields['billing']['billing_area']['label'] = 'Area';
    $fields['billing']['billing_area']['required'] = 'True';
    $fields["billing"]["billing_area"]["type"] = 'select';
    $fields["billing"]["billing_area"]["class"][0] = 'form-row-last';
    $fields['billing']['billing_area']['priority'] = 50;
    $fields["billing"]["billing_area"]["input_class"] = array(
    'state_select' => 'state_select'
    );
    
    $city = $_REQUEST['billing_city'];
    
    if ($city == 'Lahore') {    
    $fields["billing"]["billing_area"]["options"] = array(
        'Naval Town' => 'Naval Town',
        'Bahria Town' => 'Bahria Town',
        'Faisal Town' => 'Faisal Town'
        );
    }
    else ($city == 'Karachi') {
    $fields["billing"]["billing_area"]["options"] = array(
        'Walton Road' => 'Walton Road',
        'Zest Road' => 'Zest Road'
        );
     }
     return $fields;
}

Here is the screenshot enter image description here

But I am getting this error

Notice:
Undefined index: billing_city in …wp-content/plugins/custom-plugin/index.php on line 35

How to fixed this error? What I am doing wrong?

Upvotes: 1

Views: 1844

Answers (1)

LoicTheAztec
LoicTheAztec

Reputation: 253886

To synch a custom checkout select field from another select field, it requires to use jQuery.

Also you can merge both functions as they use the same hook.

Below in the first function, we keep your cities / areas settings that we can call everywhere. The last function enable dynamic options changes on the "Billing areas" dropdown depending on the chosen city:

function cities_areas_settings() {
    $text_domain = 'woocommerce';

    return array(
        __('Lahore', $text_domain) => array(
            __('Naval Town', $text_domain),
            __('Bahria Town', $text_domain),
            __('Faisal Town', $text_domain),
        ),
        __('Karachi', $text_domain) => array(
            __('Walton Road', $text_domain),
            __('Zest Road', $text_domain),
        )
    );
}

add_filter( 'woocommerce_checkout_fields', 'custom_checkout_fields' );
function custom_checkout_fields( $fields ) {
    // Initializing
    $text_domain   = 'woocommerce';
    $option_cities = array();
    $lahore_areas  = array( '' => __('Choose your area', $text_domain) );

    // Load settings and prepare options arrays
    foreach( cities_areas_settings() as $city => $areas ) {
        $option_cities[$city] = $city;
        if( $city === 'Lahore' ) {
            foreach( $areas as $area ) {
                $lahore_areas[$area] = $area;
            }
        }
    }

    // 1. Billing City field
    $fields['billing']['billing_city']['type']        = 'select';
    $fields['billing']['billing_city']['class']       = array('form-row-first');
    $fields['billing']['billing_city']['input_class'] = array('state_select');
    $fields['billing']['billing_city']['options']     = $option_cities;

    // 2. Billing Area Field
    $fields['billing']['billing_area'] = array(
        'type'        => 'select',
        'label'       => __('Area', $text_domain),
        'class'       => array('form-row-last'),
        'input_class' => array('state_select'),
        'options'     => $lahore_areas,
        'required'    => true,
        'default'     => '',
        'priority'    => 50,
    );

    return $fields;
}

add_action('wp_footer', 'custom_checkout_js_script');
function custom_checkout_js_script() {
    if( is_checkout() && ! is_wc_endpoint_url() ) :
    // Initializing
    $text_domain   = 'woocommerce';
    $karachi_areas = array( '' => __('Choose your area', $text_domain) );

    $settings = cities_areas_settings(); // Load settings

    // Prepare 'Karachi' options dropdown
    foreach( cities_areas_settings()['Karachi'] as $area ) {
        $karachi_areas[$area] = $area;
    }

    ?>
    <script language="javascript">
    jQuery( function($){
        var a = 'select[name="billing_city"]',
            b = 'select[name="billing_area"]',
            o = <?php echo json_encode($karachi_areas); ?>,
            s = $(b).html();

        // Utility function to fill dynamically the select field options
        function dynamicSelectOptions( opt ){
            var options = '';
            $.each( opt, function( key, value ){
                options += '<option value="'+key+'">'+value+'</option>';
            });
            $(b).html(options);
        }

        // On Start (once DOM is loaded)
        if ( $(a).val() === 'Karachi' ) {
            dynamicSelectOptions( o );
        }

        console.log($(a).val());

        // On billing city change live event
        $('form.woocommerce-checkout').on('change', a, function() {
            console.log($(this).val());
            if ( $(this).val() === 'Karachi' ) {
                dynamicSelectOptions( o );
            } else {
                $(b).html(s);
            }
        });
    });
    </script>
    <?php
    endif;
}

Code goes in functions.php file of your active child theme (or active theme). Tested and works.

Related: Dynamic synched custom checkout select fields in WooCommerce

Upvotes: 2

Related Questions