skip to Main Content

In woocommerce, I have 2 selects fields:

  • The first one is “Car Brands”,
  • And the second one is “Car Models” of these Car Brands.

What I would like to do is to get dynamically “Car Models” for the selected “Car Brand”

The “Car Brands” come from WooCommerce product attributes taxonomies. For each “car brand”, the related “car models” are the terms of this product attribute taxonomy.

Here is the code for “Car Brands” (the first select field):

$attributes =  wc_get_attribute_taxonomies();

if($attributes) {
    echo '<select id="car-brands"><option value="noselection">Car Brand</option>';
    foreach ( $attributes as $attribute ) {
        echo '<option value="' . $attribute->attribute_name . '">' . $attribute->attribute_label . '</option>';
    }
    echo '</select>';
}

And a generated html sample code:

<select id="car-brands">
    <option value="noselection">Car Brand</option>
    <option value="toyota">TOYOTA</option>
    <option value="lexus">LEXUS</option>
</select>

Then the code for “Car models” (the second select field):

$selected_attribute_name = 'toyota';
$taxonomy = 'pa_' . $selected_attribute_name;
$term_names = get_terms( array( 'taxonomy' => $taxonomy, 'fields' => 'names' ) );

echo '<select id="car-models"><option value="noselection">Car Model</option>';
echo '<option>' . implode( '</option><option>', $term_names ) . '</option>';
echo '</select>';

And a generated html sample code:

<select id="car-models">
    <option value="noselection">Car Model</option>
    <option value="toyota">AVENSIS</option>
    <option value="lexus">CAMRY</option>
</select>

As you can see I’m getting the specific car models for “toyota” brand, because I have hard coded “toyota” as “Car brand”:

$selected_attribute_name = 'toyota';

So what I would like is to have $selected_attribute_name as a dynamic variable, so when user select the car brand “LEXUS” or “TOYOTA”, second select field loads dynamically the related terms (options).

I found a lot of related threads, but I haven’t be able to understand how can I make it work on my case.

How I can have dynamic “car models” select field options based on selected car brand?


EDIT

All my php is in a action hook function like so:

function _themename_woocommerce_custom_filter() {
    $attributes =  wc_get_attribute_taxonomies();

    if($attributes) {
        echo '<select id="car-brands"><option value="noselection">Car Brand</option>';
        foreach ( $attributes as $attribute ) {
            echo '<option value="' . $attribute->attribute_name . '">' . $attribute->attribute_label . '</option>';
        }
        echo '</select>';
    }

    $selected_attribute_name = '';
    $taxonomy = 'pa_' . $selected_attribute_name;
    $term_names = get_terms( array( 'taxonomy' => $taxonomy, 'fields' => 'names' ) );

    echo '<select id="car-models"><option value="noselection">Car Model</option>';
    echo '<option>' . implode( '</option><option>', $term_names ) . '</option>';
    echo '</select>';
}
add_action( 'woocommerce_before_shop_loop', '_themename_woocommerce_custom_filter', 3 );

2

Answers


  1. Here take a look at a working ajax example.

    Javascript Part:

    jQuery('#car-brands').change(function() {
        let carBrandName = jQuery(this).val();
        YourFunctionNameHere(carBrandName);
    });
    
    //function to execute
    function YourFunctionNameHere(carBrandName) {
        //formdata variable consists of
        //action: this is ajax action name for WordPress which we define in PHP with a callback function with same name. See in PHP code part.
        //brandName: this is your custom post attributes name
        let formdata = "action=get_car_models&brandName="+carBrandName;
        jQuery.ajax({
            type: "POST",
            url: ajaxurl, // since WordPress version 2.8 ajaxurl is always defined in the admin header and points to admin-ajax.php
            data: formdata,
            cache: false,
            success: function(response, textStatus, jqXHR) {
                jQuery("#car-models").html(response);
            },
            error: function(jqXHR, textStatus, errorThrown) {
                //do stuff here in case of error
            }
        });
    }
    

    PHP Part:

     //here wp_ajax is the required prefix for your custom actions
     //first parameter is action name with wp_ajax prefix
     //second parameter is callback function to execute with same name as your action
     //for example if your action name is wp_ajax_get_car_models then your callback will be get_car_models
    add_action( 'wp_ajax_get_car_models', 'get_car_models' );
    
    function get_car_models() {
        global $wpdb; // this is how you get access to the database
    //require_once any files here in which the below code is available or just write your code here.
        $selected_attribute_name = $_POST['brandName'];
        $taxonomy = 'pa_' . $selected_attribute_name;
        $term_names = get_terms( array( 'taxonomy' => $taxonomy, 'fields' => 'names' ) );
        $html = '';
        $html .= '<select id="car-models"><option value="noselection">Car Model</option>';
        $html .= '<option>' . implode( '</option><option>', $term_names ) . '</option>';
        $html .= '</select>';
        echo $html;
        wp_die(); // this is required to terminate immediately and return a proper response
    
    }
    
    Login or Signup to reply.
  2. The following uses Ajax to get the corresponding terms from the selected “car brand” (product attribute taxonomy) to generate dynamically the “car model” select field options (terms of the selected product attribute taxonomy):

    // Display 2 select fields (car brands and car models)
    add_action( 'woocommerce_before_shop_loop', 'before_shop_loop_action_callback', 3 );
    function before_shop_loop_action_callback() {
        if( $attributes =  wc_get_attribute_taxonomies() ) {
    
            ## 1st dropdown
    
            echo '<select id="car-brands" style="min-width:100px;"><option value="">' . __("Car Brand"). '</option>';
    
            // Loop through attribute taxonomies
            foreach ( $attributes as $attribute ) {
                echo '<option value="' . $attribute->attribute_name . '">' . $attribute->attribute_label . '</option>';
            }
            echo '</select>';
    
            ## 2nd dropdown
    
            echo '<select id="car-models" style="min-width:100px;"><option value=""> … </option></select>';
        }
    }
    
    // jQuery / Ajax (client side)
    add_action( 'wp_footer', 'car_brand_selectors_script' );
    function car_brand_selectors_script() {
        ?>
        <script type="text/javascript">
        jQuery(function( $ ) {
            if (typeof woocommerce_params === 'undefined')
                return false;
    
            var b = 'select#car-brands', // 1st field
                m = 'select#car-models', // 2nd field
                r = $(m).html(); // Original 2nd field select options
    
            function ajaxSendCarBrand( carBrand ) {
                $.ajax({
                    url: woocommerce_params.ajax_url,
                    type : 'POST',
                    data : {
                        'action' : 'get_brand_terms',
                        'car_brand' : carBrand
                    },
                    success: function( response ) {
                        var options = $.parseJSON(response),
                            opt     = '';
    
                        if ( $.isEmptyObject(options) ) {
                            $(m).html(r);
                        } else {
                            $.each( options, function( key, value ){
                                opt += '<option value="'+key+'">'+value+'</option>';
                            });
                            $(m).html(opt);
                        }
                    }
                });
            }
    
            // On change live event
            $( document.body ).on( 'change', b, function() {
                ajaxSendCarBrand($(this).val());
            });
        });
        </script>
        <?php
    }
    
    // WP AJAX HANDLER (Server side)
    add_action('wp_ajax_get_brand_terms', 'get_car_brand_models');
    add_action('wp_ajax_nopriv_get_brand_terms','get_car_brand_models');
    function get_car_brand_models() {
        if( isset($_POST['car_brand']) ) {
            $brand    = wc_clean( $_POST['car_brand'] );
            $taxonomy = wc_attribute_taxonomy_name($brand);
            $options  = [];
    
            if( taxonomy_exists( $taxonomy ) ) {
                $terms   = get_terms( array( 'taxonomy' => $taxonomy ) );
    
                foreach( $terms as $term ){
                    $options[$term->slug] = $term->name;
                }
            }
            echo json_encode( $options );
        }
        wp_die();
    }
    

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

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search