Blog

Crear dropdowns anidados con categorías/taxonomías en WordPress

En estos últimos proyectos he estado aprendiendo mucho de WordPress y creo que es bueno poder compartir un poco de lo que aprendo con tutoriales pequeñitos pero útiles para tu próximo proyecto.

El problema

Deseo mostrar solo los hijos de una categoría dependiendo del padre que se elige, por ejemplo; tengo un blog de tecnología y la jerarquía de categorías es así:

  • Internet
    • Servidores
    • CMS
    • html/css
  • OS
    • Windows
    • Mac/OS
    • Linux
  • Gargets
    • Móviles
    • Computadoras
    • Otros

Y en mi búsqueda yo deseo dependiendo el padre (internet, OS, Gargets) mostrar los hijos.

Las bases

Sabemos que las categorías son una taxonomía predefinida de WordPress  que es jerárquica es decir, tiene niveles. Niveles que podemos controlar con funciones de WordPress o creando funciones por medio de filtros.

Utilizaremos el plugin de jquery Chained Selects y con eso haremos que nuestro concatenado funcione.

Para categorías/taxonomías, primero creamos una función (como la que utilizamos para el tutorial de búsqueda avanzada) y luego la modificamos para usarlas, no se preocupen explicaré cada paso.

¡Y el tutorial!

Primero creamos la función que nos listará nuestros elementos padres (los de primer nivel).

function get_parent_terms_dropdown($taxonomies, $args = array(), $selectid = ''){
$defaults = array(
 'parent' => 0
 );
$args = wp_parse_args( $args, $defaults );
$myterms = get_terms($taxonomies, $args);
 $output = "<select id='". $selectid ."'>";
$subout = "<select id='". $selectid ."-sub'>";
foreach($myterms as $term){$output .="<option value='" . $term->slug . "'>".$term->name."</option>";
 $defaults = array(
 'parent' => $term->term_id
 );
 $args = wp_parse_args( $defaults, $args );

 $subterms = get_terms($taxonomies, $args);
 if($subterms){
 foreach($subterms as $s){
 $subout .="<option class='". $term->slug ."' value='" . $s->slug."'>" . $s->name . "</option>";
 }
 }
 }
$output .= "</select>";
 $subout .= "</select>";
 return $output . $subout;
}

Esta función recoge 3 parámetros:

  • $taxonomies que es la taxonomía (si quieres listar categorías, escribes category). La razón por la que la hago así es para tener una función que nos de los 2 resultados que deseamos para taxonomías y para categorías (por eso no utilizo get_category() ).
  • $arg que son los argumentos de filtrado, los puedes encontrar en la referencia de get_terms().
  • $selectid es el nombre que le pondremos a nuestro select para luego llamarlo con javascript.

La función que llama a las subcategorías de nuestra taxonomía

Esta función es muy parecida, simplemente que envuelve un loop dentro de otro, usando el parámetro del padre para poder obtener los hijos.

function get_child_terms_dropdown($taxonomies, $args){
$mychildterms = get_terms($taxonomies, $args);
$output = ''; //creo una variable para la cual mostraré las opciones del select
foreach($mychildterms as $term){
$term_name =$term->name;
$termino = $term_name;
$existe_termino = term_exists( $termino, $taxonomies);
$termino_id = $existe_termino['term_id'];
//genero otro loop con los argumentos donde el importante es child_of
$child_args = array('orderby'=>'name','hide_empty'=>false,'child_of'=>$termino_id);
$child_terms = get_terms($taxonomies, $child_args);
foreach($child_terms as $child_term) {
$child_name = $child_term->name;
$child_slug = $child_term->slug;
$output .="<option class='". $term_name ."' value='".$child_slug."'>".$child_name."</option>";
}
}
return $output;

Ahora ya que tenemos las funciones en functions.php, es hora de la magía. La función nueva ya hace todo el trabajo!

Modificando el template

Una vez tenemos las funciones es lo más simple. Abres la parte donde quieres tener tu formulario de categorías (taxonomías) concatenado. Y pegas el siguiene código.

<form method="get" id="searchform" action="<?php bloginfo('home'); ?>/">
<?php
$taxonomies = 'ubicacion'; //eliges la taxonomía que deseas mostrar
$selectid = 'mark'; //este es el id para tu chain
$args = array('orderby'=>'name','hide_empty'=>false,'parent'=>0);
$ubicacion_select = get_parent_terms_dropdown($taxonomies, $args, $selectid); ?>
<?php echo $ubicacion_select; ?>
<?php
$area_child_select = get_child_terms_dropdown($taxonomies, $args); ?>
<select id="series" name="<?php echo $taxonomies; ?>">
<?php echo $area_child_select; ?>
</select>
<input name="Buscar" type="submit" value="Buscar" />
</form>

Elegí “series” por que  ya está así en el tutorial de chained selects, pero lo pueden cambiar por el que deseen.

<form method="get" id="searchform" action="<?php bloginfo('home'); ?>/">
<?php
$taxonomies = 'ubicacion'; //eliges la taxonomía que deseas mostrar
$selectid = 'mark'; //este es el id para tu chain
echo get_parent_terms_dropdown($taxonomies, null, $selectid); ?>
<input name="Buscar" type="submit" value="Buscar" />
</form>

Esto hará que tengamos 2 selects, uno con los términos padres y otro con todos los términos hijos.

Haciendo mágia, el javascript

Una vez tenemos nuestros selects con sus respectivos id’s, en nuestro ejemplo mark y series. Agregamos el script de Jquery y Chained Selects y luego este script.

jQuery(function ($) {
$("#mark-sub").chained("#mark");
});

Esto dentro de las etiquetas <script type=”text/javascript”></script> utilizo jQuery por que así me ahorro posibles conflictos de javascript con otras librerías.

Actualización 19 noviembre 2013

  • Cambié el link de Chained por otro más reciente.
  • Cambié la función (era un niño y no sabía del todo que hacía)
  • La función genera un “mi nombre que le puse”-sub para el elemento “hijo”

¡Y eso es todo! ¡Ya tenemos nuestro buscador con categorías contactenadas!