Metabox desplegable de taxonomía en el back-end

9

Creé una taxonomía personalizada llamada Brandsy la hice jerárquica para poder agregar marcas y modelos de automóviles allí y mantener sus relaciones, así:

  • Vado
    • Mustango
    • Mondeo
    • Atención

El problema es que esta lista puede ser bastante larga y solo se necesita una marca y un modelo por publicación, por lo que las casillas de verificación son engañosas.

Estoy pensando en dividir ese metabox en dos (uno para la marca y otro para el modelo) y hacerlos desplegables. Entonces, cuando se selecciona la marca en el primer menú desplegable, el segundo menú desplegable solo mostrará los modelos relacionados con esa marca. Pero no tengo idea de cómo codificarlo. ¿Quizás alguien podría mostrarme un ejemplo?

Kovas
fuente

Respuestas:

10

Aquí hay un ejemplo. También he creado un Gist con un código más genérico.

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();
}
Hameedullah Khan
fuente
@Hameedullah cosas bastante pesadas hameedullah, excelente trabajo, no obstante. +1
VicePrez
@Hameedullah muy agradable. Pero tengo un problema con eso. Pegué todo este código en mis functions.php y cuando voy al back-end de la publicación, obtengo esto: Advertencia: define () espera al menos 2 parámetros, 1 dado (señalando esta línea de código:) if ( define('DOING_AUTOSAVE') && DOING_AUTOSAVE ).
Kovas
por favor cambie definir a definido, por ejemploif ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ))
Hameedullah Khan
@Hameedullah esto es genial, gracias por la solución :)
Kovas
estaba emocionado de encontrar este fragmento y lo probé en el sitio. Lo estoy usando en un tipo de publicación personalizado, no en publicaciones, pero no veo el metabox. ¿Hay pasos necesarios para que esto funcione en otros post-tipos? Cambié el nombre del impuesto a mi taxonomía personalizada, solo utilicé esto para un impuesto único, no múltiple como la persona original solicitada
shawn