Skip to content

Armando un menu amigable en WordPress sin depender del NavWalker

José Debuchy

Jul 14, 2021 | 5 min to read |

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.

Author

José Debuchy