Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make output of a select list be dependant on parent list?

Tags:

php

wordpress

I have two arrays that have a parent category and sub category each appear in a select list, how do I make the sub category show items only from its parent category?

 <?php $carMakes = array(
 'show_option_all'    => '',
 'show_option_none'   => ('All Makes'),
 'orderby'            => 'ID', 
 'order'              => 'ASC',
 'show_count'         => 0,
 'hide_empty'         => 1, 
 'child_of'           => 25,
 'exclude'            => 0,
 'echo'               => 1,
 'selected'           => 0,
 'hierarchical'       => 0, 
 'name'               => 'cat',
 'id'                 => '',
 'class'              => 'postform',
 'depth'              => 0,
 'tab_index'          => 0,
 'taxonomy'           => 'category',
 'hide_if_empty'      => false
); ?>

<?php $carModels = array(
 'name'               => 'subcat',
 'hierarchical'       => 1,
 'parent'             => get_cat_id('model'),
 'show_option_none'   => ('All Models'),
 'hide_empty'   => 0  ); 
?>

<?php wp_dropdown_categories($carMakes); ?> 

<?php wp_dropdown_categories($carModels); ?>

need to only show car models that belong to car makes for example

Make=Toyota  Model=Supra
             Model=Corolla
             Model=Tundra

Here is an example of the category structure

Make (parent category)
     -Toyota
     -Nissan
     -Mazda
     -Ford

    Model (parent category)
     -Supra
     -Skyline
     -Mustang
     -Rx7
     -Corolla
like image 422
zadubz Avatar asked Apr 01 '13 18:04

zadubz


1 Answers

Always wanted to do an exercise on chained selections using Ajax, so, here we go ;)

This is a full plugin and should be installed in wp-content/plugins/your-plugin-name folder. Consists of three files, the plugin itself, the Javascript file and the Ajax loader image.

Install the plugin and activate, and insert the following in some theme template file:

<?php 
if( class_exists( 'BRSFL_Chained_Selection' ) ) {
    // Parameters: ( $cat_id, $dropdown_text )
    BRSFL_Chained_Selection::print_cats( 1, 'All Makes' ); 
}
?>

Also, adjust the two calls to wp_dropdown_categories as desired. Check the code comments for details.

The sub-categories dropdown is modified in response to changes in the categories dropdown:

enter image description here

chained-categories.php

<?php
/**
 * Plugin Name: Chained Categories
 * Plugin URI: http://stackoverflow.com/q/15748968/1287812
 * Description: Demonstration of chained categories with Ajax. 
 *   Plugin structure based on <a href="https://gist.github.com/3804204">Plugin Class Demo</a>, by Thomas Scholz.
 *   Use the dropdowns in the theme with this PHP method call: BRSFL_Chained_Selection::print_cats();
 * Author: Rodolfo Buaiz
 * Author URI: http://wordpress.stackexchange.com/users/12615/brasofilo
 */

add_action(
    'plugins_loaded',
    array ( BRSFL_Chained_Selection::get_instance(), 'plugin_setup' )
);

class BRSFL_Chained_Selection
{
    /**
     * Plugin instance.
     *
     * @see get_instance()
     * @type object
     */
    protected static $instance = NULL;

    /**
     * URL to this plugin's directory.
     *
     * @type string
     */
    public $plugin_url = '';

    /**
     * Path to this plugin's directory.
     *
     * @type string
     */
    public $plugin_path = '';

    /**
     * Access this plugin’s working instance
     *
     * @wp-hook plugins_loaded
     * @since   2012.09.13
     * @return  object of this class
     */
    public static function get_instance()
    {
        NULL === self::$instance and self::$instance = new self;
        return self::$instance;
    }

    /**
     * Used for regular plugin work.
     *
     * @wp-hook plugins_loaded
     * @since   2012.09.10
     * @return  void
     */
    public function plugin_setup()
    {    
        $this->plugin_url    = plugins_url( '/', __FILE__ );
        $this->plugin_path   = plugin_dir_path( __FILE__ );
        $this->load_language( 'chainedselections' );

        add_action( 'wp_enqueue_scripts', array( $this, 'script_enqueuer' ) );
        add_action( 'wp_ajax_custom_query', array( $this, 'custom_query' ) );
        add_action( 'wp_ajax_nopriv_custom_query', array( $this, 'custom_query' ) );
    }

    /**
     * Constructor. Intentionally left empty and public.
     *
     * @see plugin_setup()
     * @since 2012.09.12
     */
    public function __construct() {}    

    /**
     * Enqueue frontend scripts
     */
    public function script_enqueuer() 
    {
        wp_register_script( 
             'ajax-quote' 
            , plugin_dir_url( __FILE__ ) . '/ajax.js'
            , array( 'jquery' ) 
        );

        wp_enqueue_script( 'ajax-quote' );

        wp_localize_script( 
             'ajax-quote' 
            , 'wp_ajax' 
            , array( 
                 'ajaxurl'  => admin_url( 'admin-ajax.php' ) 
                , 'ajaxnonce' => wp_create_nonce( 'ajax_chained_selection_validate' )
                , 'icon' => plugin_dir_url( __FILE__ ) . '/ajax-loader.gif' 
            ) 
        );
    }    

    /**
     * Ajax create sub-categories dropdown
     */
    public function custom_query()
    {
        // Security
        check_ajax_referer( 'ajax_chained_selection_validate', 'security' );

        // Check if jQuery posted the data
        if( !isset( $_POST[ 'chained_subcat_id' ] ) )
            return false;

        // Adjust parameters
        $carMakes = array(
            'show_option_all'    => '',
            'show_option_none'   => 'All ' . $_POST[ 'chained_subcat_name' ],
            'orderby'            => 'ID', 
            'order'              => 'ASC',
            'show_count'         => 0,
            'hide_empty'         => 0, 
            'exclude'            => 0,
            'echo'               => 1,
            'selected'           => 0,
            'child_of'           => $_POST[ 'chained_subcat_id' ],
            'hierarchical'       => 1, 
            'name'               => 'chained-subcontainer',
            'id'                 => '',
            'class'              => 'postform',
            'depth'              => 1,
            'tab_index'          => 0,
            'taxonomy'           => 'category',
            'hide_if_empty'      => false
        ); 

        // Print sub-categories
        wp_dropdown_categories( $carMakes );
        exit();
    }       

    /**
     * Loads translation file.
     *
     * Accessible to other classes to load different language files (admin and
     * front-end for example).
     *
     * @wp-hook init
     * @param   string $domain
     * @since   2012.09.11
     * @return  void
     */
    public function load_language( $domain )
    {
        $locale = apply_filters( 'plugin_locale', get_locale(), $domain );

        // Load translation from wp-content/languages if exist
        load_textdomain(
                $domain, WP_LANG_DIR . $domain . '-' . $locale . '.mo'
        );

        // Load regular plugin translation
        load_plugin_textdomain(
            $domain,
            FALSE,
            $this->plugin_path . '/languages'
        );
    }

    /**
     * Print the dropdown in the frontend
     */
    public static function print_cats( $cat_id, $dropdown_text )
    {
        // Adjust parameters
        $carMakes = array(
            'show_option_all'    => '',
            'show_option_none'   => $dropdown_text,
            'orderby'            => 'ID', 
            'order'              => 'ASC',
            'show_count'         => 0,
            'hide_empty'         => 0, 
            'exclude'            => 0,
            'echo'               => 1,
            'selected'           => 0,
            'child_of'           => $cat_id,
            'hierarchical'       => 1, 
            'name'               => 'chained-categories',
            'id'                 => '',
            'class'              => 'postform',
            'depth'              => 1,
            'tab_index'          => 0,
            'taxonomy'           => 'category',
            'hide_if_empty'      => false
        ); 

        // Print categories
        wp_dropdown_categories( $carMakes );

        // Empty dropdown for sub-categories
        echo '<div id="chained-subcontainer">
                <select name="chained-subcategories" id="chained-subcategories">
                    <option value="">- Select a category first -</option>
                </select>
            </div>';
    }
}

ajax.js

jQuery( document ).ready( function( $ ) 
{ 
     var data = {
         action: 'custom_query',
         security: wp_ajax.ajaxnonce
     };

    $( "#chained-categories" ).on( "change", function( e ) 
    {
        // Add specific data to the variable, used to query the sub-categories
        data[ 'chained_subcat_id' ] = $( this ).val();
        data[ 'chained_subcat_name' ] = $(
            '#chained-categories option[value=' 
            + $( this ).val() 
            + ']'
            ).text();

        // A sub-category was selected
        if( $( this ).val() > 0 )
        {
            // Ajax loader icon 
            $( '#chained-subcontainer' ).html( '<img src="' + wp_ajax.icon + '">' );

            // Ajax call
            $.post( 
                wp_ajax.ajaxurl, 
                data,   
                // No error checking is being done with the response                
                function( response )
                {
                    $( '#chained-subcontainer' ).html( response );
                }
            );
        }
        // No selection, show default
        else
        {
            $( '#chained-subcontainer' ).html( '<select name="chained-subcategories" id="chained-subcategories"><option value="">- Select a category first -</option></select>' );
        }           
    });
} );

ajax-loader.gif

ajax loader

like image 154
brasofilo Avatar answered Sep 27 '22 19:09

brasofilo