Armando un menu amigable en WordPress sin depender del NavWalker
José Debuchy
Wordpress
¿Cuántas veces nos dimos la cabeza contra la pared tratando de editar un NavWalker de WordPress? Esta clase, basada en la clase abstracta Walker, es poco práctica, y editar los menus a la medida que uno quiere suele ser una tarea complicada. Para evitar esto, vamos a utilizar un paquete de composer que permite tener mucho mayor control sobre la navegación y adaptarla a la medida que uno quiere:
https://github.com/Log1x/navi/
Este paquete funciona a la perfección con Sage 10.
Instalación
Dentro de la carpeta del theme corremos
composer require log1x/navi
Uso con Sage 10
Setup Menu
Comenzamos por el lado de WordPress. En la carpeta app
tenemos el archivo setup.php
donde, por default, tenemos registrado el menu Primary Navigation. También se podrían agregar otros menus (como en el ejemplo) si fuera necesario.
/**
* Register navigation menus
* @link <https://developer.wordpress.org/reference/functions/register_nav_menus/>
*/
register_nav_menus([
'primary_navigation' => __('Primary Navigation', 'sage'),
'footer_menu' => __('Footer Menu', 'sage'),
]);
Creación de Menu
Vamos al panel de WordPress y, dentro de Appearence/Menus
creamos un nuevo menu. Por default WP trae uno.
Asignación de Ubicación
Agregamos todos los items que consideramos necesarios dentro del menu y grabamos. Una vez grabado el menu elegimos la ubicación que queremos asignarle, basándonos en los registros creados en el paso 1. En este caso, en Display location
elegimos la opción Primary Navigation
.
El Menu Name que aparece en el panel de WordPress no tiene nada que ver con el nombre con el que registramos el paso 1, pero generalmente mantenemos una relación 1 a 1 por lo tanto es saludable que tengan un nombre igual o similar.
Creación de View Composer mediante Acorn
Una vez que tenemos el menu que queremos mostrar creado, vamos al código. Mediante la extensión de Acorn de la cli creamos un View Composer llamado Navigation.
# site/web/app/themes/sage
wp acorn make:composer Navigation
Definición de variables y archivos adonde se expondrán
En nuestro caso, vamos a exponer la variable $navigation
(que será generada gracias al método Navi::build('primary_navigation')->toArray()
que provee el paquete) a la vista partials.navigation
.
El View Composer se encontrará en theme-name/app/View/Composers/Navigation.php
<?php
namespace App\\View\\Composers;
use Log1x\\Navi\\Facades\\Navi;
use Roots\\Acorn\\View\\Composer;
class Navigation extends Composer
{
/**
* List of views served by this composer.
*
* @var array
*/
protected static $views = [
'partials.navigation',
];
/**
* Data to be passed to view before rendering.
*
* @return array
*/
public function with()
{
return [
'navigation' => $this->navigation(),
];
}
/**
* Returns the primary navigation.
*
* @return array
*/
public function navigation()
{
if (Navi::build('primary_navigation')->isEmpty()) {
return;
}
return Navi::build('primary_navigation')->toArray();
}
}
Edición de partial de blade
Habiendo registrado la variable $navigation
ahora podemos editar el archivo blade de la manera que queramos. Creamos el archivo navigation.blade.php
en la carpeta theme-name/resources/views/partials/
y editamos el menu de la manera que queramos.
Podemos tomar algunos ejemplos de la documentación de Bootstrap. En nuestro caso, vamos a utilizar uno de los ejemplos de navbar.
@if ($navigation)
<div class="collapse navbar-collapse" id="main-navbar">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
@foreach ($navigation as $item)
<li class="nav-item{{ $item->children ? ' dropdown' : '' }}">
@if (!$item->children)
<a class="nav-link {{ $item->classes ?? '' }} {{ $item->active ? ' active' : '' }}" href="{{ $item->url }}">{!! $item->label !!}</a>
@else
<a class="nav-link dropdown-toggle" href="#" id="dropdown-{{ $loop->index }}" data-bs-toggle="dropdown" aria-expanded="false">{!! $item->label !!}</a>
<ul class="dropdown-menu" aria-labelledby="dropdown-{{ $loop->index }}">
@foreach ($item->children as $child)
<li>
<a class="dropdown-item {{ $child->classes ?? '' }} {{ $child->active ? 'active' : '' }}" href="{!! $child->url !!}">{!! $child->label !!}</a>
</li>
@endforeach
</ul>
@endif
</li>
@endforeach
</ul>
<form>
<input class="form-control" type="text" placeholder="Search" aria-label="Search">
</form>
</div>
@endif
Inclusión de partial
Por último, en el partial del header theme-name/resources/views/partials/header.blade.php
vamos a llamar a este partial de navegación mediante la directiva @include
, lo que nos permite tener un código limpio y reutilizable que puede ser utilizado en otros lugares del sitio. Este es un ejemplo sencillo que puede ser acomodado a las necesidades de cada proyecto.
<header class="banner">
<div class="container">
<div class="d-flex justify-content-lg-between align-items-center">
<a class="brand" href="{{ home_url('/') }}">
<img src="@option('logo', 'url')" alt="@option('logo', 'alt')">
</a>
<nav class="nav-primary align-items-lg-center" id="primary-navigation" tabindex="-1">
@include('partials.navigation')
</nav>
</div>
</div>
</header>
Resultado final
Aquí tenemos el resultado final del menú. En este caso no lo mostramos, pero si hubiera un dropdown de un nivel se mostraría en forma automática como lo hace Bootstrap.
En caso de tener mayores requerimientos, en la documentación del paquete se puede observar la respuesta que obtendremos de la variable $navigation
.