9

I've created custom taxonomy called Brands and made it hierarchical so I can add Car brands and models there and keep their relations, like this:

  • Ford
    • Mustang
    • Mondeo
    • Focus

Problem is, this list might get pretty long and only one brand and one model is needed per post, so checkboxes are misleading.

I'm thinking to split that metabox in to two (one for brand and one for model) and make them dropdowns. So when brand is selected in the first dropdown, second dropdown would show only models related to that brand. But i have no idea how to code it. Maybe anyone could show me an example?

1 Answer 1

10

Here is an example. I have also created a Gist with more generic code.

add_action('add_meta_boxes', 'my_custom_metabox');
function my_custom_metabox() {
    add_meta_box('custom-taxonomy-dropdown','Brands','taxonomy_dropdowns_box','post','side','high');
}

function taxonomy_dropdowns_box( $post ) {
    wp_nonce_field('custom-dropdown', 'dropdown-nonce');
    $terms = get_terms( 'brands', 'hide_empty=0');
    $object_terms = wp_get_object_terms( $post->ID, 'brands', array('fields'=>'ids'));

    // you can move the below java script to admin_head
?>
    <script type="text/javascript">
        jQuery(document).ready(function() {
                jQuery('#custombrandoptions').change(function() {
                    var custombrand = jQuery('#custombrandoptions').val();
                    if ( custombrand == '0') {
                        jQuery('#custommodeloptions').html('');
                            jQuery('#modelcontainer').css('display', 'none');
                    } else {
                        var data = {
                            'action':'get_brand_models',
                            'custombrand':custombrand,
                            'dropdown-nonce': jQuery('#dropdown-nonce').val()
                        };
                        jQuery.post(ajaxurl, data, function(response){
                            jQuery('#custommodeloptions').html(response);
                            jQuery('#modelcontainer').css('display', 'inline');
                        });
                    }
                });
        });
    </script>
    <?php
    echo "Brand:";
    echo "<select id='custombrandoptions' name='custombrands[]'>";
    echo "<option value='0'>None</option>";
    foreach ( $terms as $term ) {
        if ( $term->parent == 0) {
            if ( in_array($term->term_id, $object_terms) ) {
                $parent_id = $term->term_id;
                echo "<option value='{$term->term_id}' selected='selected'>{$term->name}</option>";
            } else {
                echo "<option value='{$term->term_id}'>{$term->name}</option>";
            }
        }
    }
    echo "</select><br />";
    echo "<div id='modelcontainer'";
    if ( !isset( $parent_id)) echo " style='display: none;'";
    echo ">";
    echo "Models:";
    echo "<select id='custommodeloptions' name='custombrands[]'>";
    if ( isset( $parent_id)) {
        $models = get_terms( 'brands', 'hide_empty=0&child_of='.$parent_id);
        foreach ( $models as $model ) {
             if ( in_array($model->term_id, $object_terms) ) {
                echo "<option value='{$model->term_id}' selected='selected'>{$model->name}</option>";
            } else {
                echo "<option value='{$model->term_id}'>{$model->name}</option>";
            }
        }
    }
    echo "</select>";
    echo "</div>";
}

add_action('save_post','save_my_custom_taxonomy');
function save_my_custom_taxonomy( $post_id ) {
    if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE )
        return;

    if ( !wp_verify_nonce($_POST['dropdown-nonce'], 'custom-dropdown'))
        return;

    $brands = array_map('intval', $_POST['custombrands']);
    wp_set_object_terms($post_id, $brands, 'brands');
}

add_action('wp_ajax_get_brand_models', 'get_brand_models');
function get_brand_models() {
    check_ajax_referer('custom-dropdown', 'dropdown-nonce');
    if (isset($_POST['custombrand'])) {
        $models = get_terms( 'brands', 'hide_empty=0&child_of='. $_POST['custombrand']);
        echo "<option value='0'>Select one</option>";
        foreach ($models as $model) {
            echo "<option value='{$model->term_id}'>{$model->name}</option>";
        }
    }
    die();
}
10
  • @Hameedullah pretty heavy stuff hameedullah, great job nonetheless. +1
    – VicePrez
    May 29, 2011 at 6:51
  • @Hameedullah very nice. But I have a problem with it. I pasted all this code to my functions.php and when I go to the post back-end, I get this: Warning: define() expects at least 2 parameters, 1 given in (pointing to this line of code: if ( define('DOING_AUTOSAVE') && DOING_AUTOSAVE )).
    – Kovas
    May 29, 2011 at 10:45
  • please change define to defined e.g if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE )) May 29, 2011 at 12:47
  • @Hameedullah this is great, thanks for solution :)
    – Kovas
    May 29, 2011 at 13:56
  • was excited to find this snippet and tried it on site. I am using it on a custom post-type, not posts, but do not see the metabox. are there steps needed to make this work on other post-types? ..I did change the tax name to my custom taxonomy, only using this for single tax, not multi like the original person requested
    – shawn
    Jun 15, 2011 at 4:00

Not the answer you're looking for? Browse other questions tagged or ask your own question.