Clase current-menu-item para el padre de un tipo de contenido personalizado

4 nov 2013, 19:48:02
Vistas: 16K
Votos: 1

Tengo un problema con mi menú y un tipo de contenido personalizado.

Tengo un custom post type llamado "services" (servicios). He creado una nueva página para ello llamada Servicios. En esa página muestro una lista de todos los posts de ese tipo de contenido. La clase current-menu-item funciona como se espera.

Pero el problema aparece cuando hago clic en uno de los servicios y voy a mysite.com/services/service-1, la clase current-menu-item de la página Servicios en el menú desaparece. Necesito mostrar que este post actual es un hijo de la página Servicios.

Todos los elementos del menú tienen el mismo HTML:

<li id="menu-item-23" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-23"><a href="http://localhost/wordpress/sluzby/">Servicios</a></li>

No hay ninguna clase CSS que pueda usar para dar estilo a este enlace como padre. Algo como current-menu-parent o similar. ¿Cómo podría solucionar esto? Gracias.

2
Comentarios

probablemente se podría hacer con jQuery... ¿están todos estos tipos de publicación Service dentro del menú?

GhostToast GhostToast
4 nov 2013 20:00:52

@GhostToast en realidad solo hay un único elemento en el menú llamado Servicios. Al hacer clic se abre la página Servicios que tiene un bucle y muestra todas las publicaciones de servicios.

Richard Mišenčík Richard Mišenčík
4 nov 2013 21:27:15
Todas las respuestas a la pregunta 4
9

Normalmente incluyo la siguiente variable padre, filtro y método en mis plugins para manejar este caso. Nunca he estado seguro si esta es la forma "correcta" de hacerlo, pero se siente mejor que aplicarlo con javascript.

class Plugin_Name {
    private $parent = 'services'; // idealmente esto debería ser un ajuste en tu plugin, no una variable hard-coded por si cambia el slug de la página

    function __construct() {
        // Agregar clases al 'parent'
        add_filter( 'nav_menu_css_class', array( &$this, 'nav_parent_class' ), 10, 2 );
    }

    function nav_parent_class( $classes, $item ) {

        if ( $this->nicename == get_post_type() && ! is_admin() ) {
            global $wpdb;

            // remover cualquier clase activa del nav (blog usualmente obtiene la clase current_page_parent en páginas/posts individuales de CPT)
            $classes = array_filter($classes, ($class == 'current_page_item' || $class == 'current_page_parent' || $class == 'current_page_ancestor'  || $class == 'current-menu-item' ? false : true ));

            // obtener información de la página
            // - realmente solo queremos el post_name para compararlo con el slug del post type
            $page = get_page_by_title( $item->title, OBJECT, 'page' );

            // verificar si el slug coincide con post_name
            if( $page->post_name == $this->parent ) {
                $classes[] = 'current_page_parent';
            }

        }

        return $classes;
    }
}

Como lo solicitaste, la ruta sin plugin. No probé esto para detectar errores, solo lo adapté de la clase anterior pero debería al menos guiarte en la dirección correcta:

add_filter( 'nav_menu_css_class', 'nav_parent_class', 10, 2 );

function nav_parent_class( $classes, $item ) {
    $cpt_name = 'service';
    $parent_slug = 'services';

    if ( $cpt_name == get_post_type() && ! is_admin() ) {
        global $wpdb;

        // remover cualquier clase activa del nav (blog usualmente obtiene la clase current_page_parent en páginas/posts individuales de CPT)
        $classes = array_filter($classes, ($class == 'current_page_item' || $class == 'current_page_parent' || $class == 'current_page_ancestor'  || $class == 'current-menu-item' ? false : true ));

        // obtener información de la página
        // - realmente solo queremos el post_name para compararlo con el slug del post type
        $page = get_page_by_title( $item->title, OBJECT, 'page' );

        // verificar si el slug coincide con post_name
        if( $page->post_name == $parent_slug ) {
            $classes[] = 'current_page_parent';
        }

    }

    return $classes;
}
4 nov 2013 20:05:44
Comentarios

¿Cómo podría hacerlo sin usar un plugin? Me gustaría insertarlo en mi functions.php pero supongo que tendría que modificarse.

Richard Mišenčík Richard Mišenčík
4 nov 2013 21:27:34

Actualicé mi respuesta con una forma de hacerlo si tu CPT no está creado como un plugin.

Joey Yax Joey Yax
4 nov 2013 22:44:52

Eso no parece funcionar para mí. Cambié las variables pero sigue sin funcionar. Si entendí correctamente, ¿el código está verificando el nombre del post y comparándolo con el slug? No creo que eso funcione ya que mi CPT se llama services. Pero estoy usando rewrite a "sluzby", que en mi idioma se traduce a servicios. Sin embargo, mis posts de servicios no contienen ese slug, quiero decir que el servicio puede llamarse Webdesign por ejemplo, no Servicio Webdesign.

Así que la página que se usa para mostrar mis posts de servicios es localhost/wordpress/sluzby. Luego los posts individuales están en localhost/wordpress/sluzby/nombre-del-post.

Richard Mišenčík Richard Mišenčík
4 nov 2013 22:54:59

Está verificando dos cosas: 1) Si la publicación que se está viendo es de tu tipo de publicación personalizada ($cpt_name) y 2) busca un ítem de navegación cuyo slug sea igual a $parent_slug. Si ambas coinciden, añade una clase current_page_parent a ese ítem de navegación.

Joey Yax Joey Yax
5 nov 2013 02:01:26

No estoy seguro si estoy haciendo algo mal pero todavía no funciona. Aquí está mi código actual:

function nav_parent_class( $classes, $item ) { $cpt_name = 'services'; $parent_slug = 'sluzby';

if ...

return $classes;

}

Así que el nombre de mi tipo de publicación personalizada es "services" y mi URL para la página de servicios es localhost/wordpress/sluzby. Luego cada servicio individual está en localhost/wordpress/sluzby/nombre-del-servicio.

Revisé el código fuente pero la clase no se está añadiendo y todas las demás clases desaparecieron. También modifiqué mi CSS para incluir los estilos para esta clase.

Richard Mišenčík Richard Mišenčík
5 nov 2013 13:19:51

Lo extraño es que ahora, cuando comenté la línea $classes = array_filter... todo funciona. Lo cual es realmente raro.

Richard Mišenčík Richard Mišenčík
6 nov 2013 14:23:56

¡Me alegro de que lo hayas conseguido! Tener esa línea comentada debería estar bien. Me preocupa que, al estar comentada, exista una pequeña posibilidad de que el blog (si lo tienes en tu navegación) se resalte al mismo tiempo cuando veas una página individual de tu CPT.

Joey Yax Joey Yax
8 nov 2013 04:05:03

No tengo blog, así que está bien, tal vez si lo tuviera funcionaría con el código completo, sin comentar la línea de clases :) Gracias de nuevo. He elegido tu respuesta como la mejor.

Richard Mišenčík Richard Mišenčík
9 nov 2013 14:44:24

Ten en cuenta que esto solo funciona si tu elemento de navegación tiene el mismo título que la página. Recuerda que los usuarios pueden establecer un título diferente en la navegación al de la página.

adamtomat adamtomat
26 jun 2014 11:06:10
Mostrar los 4 comentarios restantes
1

Este código añade la clase 'current-menu-item' al elemento padre del menú cuando estás en un CPT hijo, taxonomía personalizada o en un post individual por defecto, en caso de que no tengas una estructura de menú anidada en el panel de administración - solo si tienes un menú de 'nivel 0'. Por ejemplo - si tienes una Página de Productos, que muestra una cuadrícula de productos y navegas a un producto individual - WordPress no reconocerá el elemento padre del menú. El siguiente código soluciona esto:

function additional_active_item_classes( $classes = array(), $menu_item = false ) {
    // taxonomía personalizada
    if ( $menu_item->title == 'Página de Taxonomía Personalizada' && is_tax('custom_tax') ) {
        $classes[] = 'current-menu-item';
    }
    // post type personalizado individual
    if ( $menu_item->title == 'Página de CPT' && is_singular('products') ) {
        $classes[] = 'current-menu-item';
    }
    // post individual del blog
    if ( $menu_item->title == 'Página del Blog' && is_singular('post') ) {
        $classes[] = 'current-menu-item';
    }
    return $classes;
}
add_filter( 'nav_menu_css_class', 'additional_active_item_classes', 10, 2 );
5 abr 2019 13:10:59
Comentarios

Hola Marek, aunque tu código puede ser correcto, ¿podrías elaborar y explicar un poco por qué esta es la respuesta y cómo funciona, para que otras personas puedan aprender de ello?

Krzysiek Dróżdż Krzysiek Dróżdż
5 abr 2019 13:40:12
0

Código final:

function nav_parent_class($classes, $item) {
    $cpt_name = 'services'; // Nombre del Custom Post Type
    $parent_slug = 'sluzby'; // Slug de la página padre

    if ($cpt_name == get_post_type() && !is_admin()) {
        global $wpdb;

        // obtener información de la página (principalmente necesitamos post_name para compararlo con el slug del post type)
        $page = get_page_by_title($item->title, OBJECT, 'page');

        // comprobar si el slug coincide con post_name
        if( $page->post_name == $parent_slug ) {
            $classes[] = 'current_page_parent';
        }

    }

    return $classes;
}

// Añadir filtro para las clases CSS del menú de navegación
add_filter('nav_menu_css_class', 'nav_parent_class', 10, 2);
6 nov 2013 17:48:32
7

Normalmente hay una clase de .current-menu-ancestor agregada a los elementos padres en la navegación.

Si no está ahí, echa un vistazo a este artículo: ¿Cómo incluir la clase 'current-menu-ancestor' en un menú de tipo de entrada personalizado en WordPress?

5 nov 2013 12:24:20
Comentarios

no me funciona. ¿Podría ser porque estoy usando rewrite y por lo tanto tengo un nombre diferente para el tipo de contenido personalizado y para la página en sí?

Richard Mišenčík Richard Mišenčík
5 nov 2013 13:24:02

¿Estás usando un menú personalizado?

Joe Joe
5 nov 2013 14:06:42

Este es el código que uso: wp_nav_menu(array( 'container' => false, 'container_class' => '', 'menu' => '', 'theme_location' => 'main-nav', 'items_wrap' => '<ul id="menu">%3$s</ul>', 'fallback_cb' => 'rm_main_nav_fallback' ));

Richard Mišenčík Richard Mišenčík
5 nov 2013 14:29:02

Y tienes el menú definido en el área de administración bajo Apariencia->Menús. Si es así y el menú aún no proporciona la clase. Este no es un problema que haya encontrado.

Joe Joe
5 nov 2013 14:40:32

Sí, he creado un Menú con todos los enlaces. Creo que podría ser un problema con la reescritura ya que el nombre de mi CPT es 'services' pero mi URL para esa página es wordpress/sluzby. Estoy realmente perdido. ¿Hay algo más que pueda intentar?

Richard Mišenčík Richard Mišenčík
5 nov 2013 14:50:58

Mmm, si crees que el problema podría estar relacionado con la reescritura, ¿has intentado no reescribir el CPT? Solo para confirmar que las páginas hijas están configuradas como 'Sub elementos del menú' en el menú

Joe Joe
5 nov 2013 15:03:03

Lo hice ahora, no funcionó. Intenté algo diferente, un ejemplo básico del codex de WordPress para esta función. Aquí está:

function rm_custom_services_class($classes, $item) {

 if(is_single() && $item->title == "Služby") {
         $classes[] = "current_page_parent";
 }

 return $classes;

}

Eso es todo y funciona. Solo me pregunto si es posible cambiar $item->title = "Služby" por algo como $item->slug == 'sluzby'. En caso de que el nombre de la página cambie.

Richard Mišenčík Richard Mišenčík
5 nov 2013 15:15:35
Mostrar los 2 comentarios restantes