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?


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() {

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('#modelcontainer').css('display', 'none');
                    } else {
                        var data = {
                            'dropdown-nonce': jQuery('#dropdown-nonce').val()
                        jQuery.post(ajaxurl, data, function(response){
                            jQuery('#modelcontainer').css('display', 'inline');
    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>";

function save_my_custom_taxonomy( $post_id ) {
    if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE )

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

    $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>";
  • @Hameedullah pretty heavy stuff hameedullah, great job nonetheless. +1 – VicePrez May 29 '11 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 '11 at 10:45
  • please change define to defined e.g if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE )) – Hameedullah Khan May 29 '11 at 12:47
  • @Hameedullah this is great, thanks for solution :) – Kovas May 29 '11 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 '11 at 4:00

protected by Community Feb 6 '12 at 16:40

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

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