Desplegable de categorías multinivel
Estoy usando WordPress como CMS y me gustaría tener categorías seleccionables desde múltiples opciones, es decir <option>
.
Como ejemplo de uso: El primer desplegable contendría las categorías padres. Luego, después de seleccionar el padre, aparecería un segundo desplegable con las categorías hijas. Hay algunos plugins disponibles en Wordpress.org pero todos parecen estar rotos o desactualizados. Agradecería cualquier ayuda.
Plugin roto http://wordpress.org/extend/plugins/ajax-category-dropdown/
El código que estoy usando de wordpress.org
<form action="<?php bloginfo('url'); ?>/" method="get">
<?php
// Mostrar desplegable de categorías con parámetros específicos
$select = wp_dropdown_categories('orderby=name&echo=0&depth=0&hierarchical=1&exclude=5,4');
// Añadir evento onchange al select
$select = preg_replace("#<select([^>]*)>#", "<select$1 onchange='return this.form.submit()'>", $select);
echo $select;
?>
<noscript><input type="submit" value="Ver" /></noscript>
</form>

function parent_child_cat_select() { ?>
<script type="text/javascript">
/* <![CDATA[ */
jQuery(document).ready(function() {
jQuery('#parent_cat').change(function(){
var parentCat=jQuery('#parent_cat').val();
// llamada ajax
jQuery.ajax({
url:"/wp-admin/admin-ajax.php",
type:'POST',
data:'action=category_select_action&parent_cat_ID=' + parentCat,
success:function(results)
{
jQuery("#sub_cat_div").html(results);
}
});
});
});
/* ]]> */
</script>
<form action="<?php bloginfo('url'); ?>/" method="get">
<div id="parent_cat_div"><?php wp_dropdown_categories("show_option_none=Selecciona categoría padre&orderby=name&depth=1&hierarchical=1&id=parent_cat"); ?></div>
<div id="sub_cat_div"><select name="sub_cat_disabled" id="sub_cat_disabled" disabled="disabled"><option>¡Primero selecciona una categoría padre!</option></select></div>
<div id="submit_div"><input type="submit" value="Ver" /></div>
</form>
<?php }
function implement_ajax() {
$parent_cat_ID = $_POST['parent_cat_ID'];
if ( isset($parent_cat_ID) )
{
$has_children = get_categories("parent=$parent_cat_ID");
if ( $has_children ) {
wp_dropdown_categories("orderby=name&parent=$parent_cat_ID");
} else {
?><select name="sub_cat_disabled" id="sub_cat_disabled" disabled="disabled"><option>¡No hay subcategorías!</option></select><?php
}
die();
} // end if
}
add_action('wp_ajax_category_select_action', 'implement_ajax');
add_action('wp_ajax_nopriv_category_select_action', 'implement_ajax');// para usuarios no logueados
// esto es opcional, solo si no estás usando jQuery
function load_jquery() {
wp_enqueue_script('jquery');
}
add_action('init', 'load_jquery');
Para mostrar los menús desplegables usa la función parent_child_cat_select()
.
<?php parent_child_cat_select(); ?>

add_action('wp_ajax_category_select_action', 'implement_ajax');//para usuarios que no han iniciado sesión. Debería ser add_action( 'wp_ajax_nopriv_category_select_action', 'implement_ajax' );

¡Gracias! Sin embargo, estoy recibiendo un mensaje que indica que no hay categorías hijas cuando en realidad hay varias.

@Zach ¿tienes publicaciones asignadas a estas categorías hijas? También ten en cuenta que esta configuración solo listará subcategorías estrictamente relacionadas.

@JohnnyPea Sí, cada una tiene varias publicaciones personalizadas. Estoy de acuerdo con que liste solo categorías estrictamente relacionadas. Por ejemplo, Cámara tendría cada una de las categorías a las que he asignado productos. Actualicé la publicación con una captura de cómo se ve mi sección de categorías. Gracias de nuevo por tu ayuda.

@Zach ¿Usas algún plugin de caché? ¿Lo probaste en otro navegador de internet? (intenta limpiar tu caché) ¿Copiaste mi código tal cual estaba? (prueba a copiar el código nuevamente) ¿No tienes algún plugin o funciones del tema que podrían interactuar con las categorías o filtrarlas de alguna manera? - puedes intentar desactivar todos los plugins y configurar el tema por defecto para ver si funciona...a mí me funciona sin plugins activos y con el tema por defecto TwentyTen

<form action="<?php echo remove_query_arg(array('mycat_go', 'cat')); ?>" method="get">
<?php
// obtener categoría seleccionada y hacer algunas inicializaciones
if (isset($_REQUEST['cat'])) $_REQUEST['mycat_go'] = $_REQUEST['cat'];
$selected = $_REQUEST['mycat_go'];
$selects = array();
$last = 0;
$top = false;
$i = 0;
// básicamente, estamos iterando desde la selección hacia arriba a través de los padres
// hasta que no haya más padres.
while (!$top) {
// preparar consulta para generar campo que contenga todas las categorías hijas
// de la seleccionada
$args = array(
'name' => 'mycat_'.$i,
'orderby' => 'name',
'echo' => 0,
'hierarchical' => 1,
'exclude' => '4,5',
'child_of' => $selected,
'depth' => 1,
'show_option_none' => '--seleccionar--',
'hide_if_empty' => true,
);
if(!empty($last)) $args['selected'] = $last;
// preparar siguiente iteración del bucle o detenerse si estamos mostrando hijos de 0
if (!empty($selected)) {
$last = $selected;
$category = get_category($selected);
$selected = $category->parent;
} else {
$top = true;
}
// generar salida y almacenar en orden inverso ya que vamos de abajo hacia arriba
$select = wp_dropdown_categories($args);
$select = preg_replace("#<option([^>]*)>#", "<option$1 onclick=\"this.parentNode.name = 'mycat_go';return this.form.submit()\">", $select);
array_unshift($selects, $select);
$i++;
}
// imprimir en pantalla
foreach ($selects as $select) {
echo $select;
}
?>
</form>
<form action="<?php remove_query_arg(array('mycat_go', 'cat')); ?>" method="get">
<input type="hidden" name="cat" value="<?php echo $_REQUEST['mycat_go']; ?>" />
<input type="submit" value="Ir allí" />
</form>
Podría usar algunos ajustes, pero debería funcionar.

jaja, eso fue bastante impresionante y tiene mucho sentido! Sin embargo hay un error en la línea 15 if(!empty($last) $args['selected'] = $last;
No estoy seguro de qué lo está causando.

@Zach Shallbetter: Vaya, eso es un error tipográfico... falta el paréntesis de cierre. Lo he editado.

Así que seguí adelante y lo agregué a la página y devolvió una lista incontable de select boxes. También tuvo un tiempo de carga enorme. Pensé que podría ser yo, así que eliminé algunas categorías y borré todo el otro código de la plantilla. No pareció resolver el problema.

@Zach Shallbetter: Parece que la condición del bucle no se activa y sigue en bucle. Ok... hice otra edición que debería evitar que el bucle sea infinito cuando no se hace una selección inicial.

Parece que solo muestra una única caja de selección con los valores secundarios. Además, cuando seleccionas un elemento no realiza ninguna acción.

@Zach Shallbetter: Lo siento, mi condición original del bucle venía de un enfoque inicial diferente y luego no lo pensé bien. Edité nuevamente y añadí algunos comentarios, espero que funcione mejor.

@Zach Shallbetter: El problema con JS debería estar resuelto ahora también.

Me disculpo por hacerte dar vueltas. El resultado que obtengo es el mismo que tenía originalmente cuando usé el código del codex. Agrego información a la categoría y la categoría aparece en el select. La selecciono y me lleva a la página. Creo que el problema puede estar en que el menú desplegable no muestra categorías vacías.

Además, no importa si el hijo tiene un padre, todo lo que aparecerá en el select es el hijo.

Agregué 'hide_empty' => 0
al array y eso me permitió ver todas las categorías incluyendo las vacías. Sin embargo, no muestra un segundo select al elegir una categoría padre, simplemente va directamente a esa página.

@Zach Shallbetter: Sí, no había pensado en eso, claro que lo haría, ya que está analizando el parámetro 'cat' en la URL. Hice otra edición que debería (con suerte) evitar eso... perdón por hacerte dar vueltas. ;-)

Ojalá esto me permitiera publicar imágenes, jeje. Así que seleccionar un elemento ahora muestra absolutamente todas las publicaciones. Tampoco muestra un segundo select cuando agrego 'hide_empty' => 0
para ver las categorías padre y seleccionar una de esas. Aún no he visto el segundo select. El problema con usar 'hide_empty' => 0
es que muestra todas las categorías en lugar de solo las padres (si eso tiene sentido).

@Zach Shallbetter: Jaja...bueno, para variar, finalmente lo probé localmente, configuré algunas categorías y demás. Ahora...funciona, más o menos. Hay algunos problemas. No sé qué tan bien se comporta con hide_empty
, pero lo básico funciona.

Todavía no hay selección secundaria, ¿hay algo de mi parte que podría causar esto?

Sí, cuando selecciono la categoría en el menú desplegable me lleva a la lista completa de entradas que pertenecen a ella.

@Zach Shallbetter: ¡Argh, hoy no es mi día en absoluto... algo salió mal al pegar el código de vuelta. Asegúrate de que sean 2 formularios separados (faltaba el último fragmento).

También considera que esto es más bien una solución rápida para inspirarse. Debería hacerse de mejor manera, como recargar solo esa parte del formulario con AJAX en lugar de recargar toda la página y cuando haya una sola entrada debería seleccionarse automáticamente, etc.

Si reemplazas todo tu fragmento de código con el fragmento de código completo de arriba, ya no debería redirigir a la página de categorías.

Dios, simplemente no sé qué estoy haciendo mal aquí. He creado una página completamente básica. Agrego una copia exacta del código anterior. Cuando selecciono "modelos" del menú desplegable (tiene 4 subcategorías). Inmediatamente salta a /?mycat_go=112 sin mostrar una selección secundaria. Gracias de nuevo por toda tu ayuda wyrfel.

Quizás hay un malentendido...se supone que debe recargar la página con ese parámetro. Así es como funciona. No está impulsado por AJAX o JS. Simplemente recarga la página con la categoría seleccionada como parámetro y luego se redibuja al cargar la página.

Ahh, creo que lo entiendo...debe ser el parámetro action
en los formularios...mira la edición.
