Como crear un menú dinámico con laravel 5.8

El menú de una página web se utiliza para  realizar la navegación entre todas sus páginas, cuando desarrollamos un menú este puede ser estático o dinámico.

¿En qué se diferencia un menú estático de uno dinámico?  Pues es bastante sencillo:

El menú estático es aquel que el programador realiza una sola vez. Para desarrollar un menú de este tipo se debe realizar con anterioridad un estudio que defina lo que se necesita mostrar en la página y así asegurar que la información nunca va a variar. Por lo general este tipo de menú se utiliza en páginas web de poca información.

El menú dinámico, por su parte, necesita de una base de datos donde se guardaran los diferentes links del menú, es muy común escuchar que desarrollar uno de estos es más difícil ya que se tiene que interactuar con la base datos y realizar consultas además de convertir la información obtenida de la misma para mostrársela al usuario. Esta clase de menú es muy útil para webs que tienen usuarios con diferentes roles y también para páginas que se crean con el fin de ir creciendo paulatinamente, en mi criterio personal es una manera muy bonita de programar porque al terminar la aplicación la web se podrá  ir adaptando según sea necesario.

Veamos entonces cómo realizar un menú dinámico sencillo donde los links del menú pueden cambiar en el futuro, en este caso no utilicé base de datos ya que solo quiero mostrar la parte del framework.

Lo primero que haremos es crear una nueva aplicación en este caso le llamaremos nav-dinamico: con la siguiente línea de código generamos la aplicación.

laravel new nav-dinamico

Una vez que se instalan todas las dependencias escribimos en la consola cd nav-dinamico y nos movemos al directorio en donde creamos el proyecto. Les comento que si escribimos cd nav y apretamos la tecla Tab en la consola se nos completa el nombre del proyecto automáticamente.

Dentro de la carpeta del proyecto escribimos code .  La palabra code, espacio,+ un punto (.) esto hace que el editor de código Visual Estudio Code se abra con el proyecto en el explorer. A continuación lo que haremos será arrancar el servidor que trae laravel por defecto con el siguiente comando

 php artisan serve

Este servidor pondrá a correr la aplicación creada en la dirección http://127.0.0.1:8000/ dando como resultado:

Hasta ahora no hemos creado menú alguno, solo hemos estado instalando lo necesario para el ejemplo.

Después iremos a routes/web.php y crearemos 5 rutas diferentes con los siguientes nombres:

Route::view('/', 'link1')       ->name('link1');
Route::view('/link2', 'link2')  ->name('link2');
Route::view('/link3', 'link3')  ->name('link3');
Route::view('/link4', 'link4')  ->name('link4');
Route::view('/link5', 'link5')  ->name('link5');

Seguidamente vamos a resources/views y creamos un fichero llamado layout.blade.php el cual lo utilizaremos como plantilla para no repetir el mismo código en todas las vistas. En dicho fichero agregamos las bibliotecas de Bootstrap para lograr una mejor vista en el diseño. Las bibliotecas podemos obtenerlas en la página oficial de Bootstrap: https://getbootstrap.com/docs/4.0/getting-started/introduction/

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">

    {{-- Biblioteca de bootstrap css --}}
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">

</head>
<body>
    {{-- El menu que se va a mostrar --}}
    @include('nav')

    {{-- El contenido de la pagina, donde se va a poner todo el contenido de las paginas --}}
    @yield('contenct')


    {{-- Bibliotecas de bootstrap js --}}
    <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
</body>
</html>

En este punto es necesario crear un fichero llamado nav.blade.php en resources/views y escribiremos nuestro código para el menú, este fichero quedaría así:

<nav class="navbar navbar-expand-lg navbar-light bg-light">

    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav mr-auto">
        <li class="nav-item active">
          <a class="nav-link" href="/">Link 1 <span class="sr-only">(current)</span></a>
        </li>
        <li class="nav-item">
          <a class="nav-link" href="/link2">Link 2</a>
        </li>
        <li class="nav-item dropdown">
          <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
            Mas link
          </a>
          <div class="dropdown-menu" aria-labelledby="navbarDropdown">
            <a class="dropdown-item" href="/link3">Link 3</a>
            <div class="dropdown-divider"></div>
            <a class="dropdown-item" href="/link4">Link 4</a>
            <div class="dropdown-divider"></div>
            <a class="dropdown-item" href="/link5">Link 5</a>
          </div>
        </li>
      </ul>
    </div>
  </nav>

El siguiente paso es ir a la dirección resources/views y crear 5 ficheros con los nombres:  

Link1.blade.php
Link2.blade.php
Link3.blade.php
Link4.blade.php
Link5.blade.php

Dentro de cada fichero escribiremos el siguiente código para verificar si las rutas funcionan. Solo cambiamos el número para diferenciar las páginas.


{{-- utilizamos la plantilla principal --}}
@extends('layout')

{{-- Contenido de esta pagina --}}
@section('contenct')
    <p>link 1</p>
@endsection

Si escribimos en el navegador la ruta http://127.0.0.1:8000/link2 este sería el resultado:

Hasta ahora lo que hemos logrado es hacer un menú estático simple pero, como el objetivo final del tutorial es crear un menú dinámico, necesitamos complicarnos un poquito más así que manos a la obra.

Lo primero que debemos saber es que son los service providers en Laravel:

Los service providers son los que se encargan de toda la configuración necesaria antes de que inicie nuestra aplicación además de todos los servicios centrales de Laravel. Los mismos funcionan cuando queremos, por ejemplo: subir un documento, generar un reporte, procesar documentos, escuchar eventos en nuestra aplicación, middleware e incluso rutas. Los service providers son el lugar central para la configuración de la aplicación. Más información aquí https://laravel.com/docs/master/providers

El siguiente paso sería ir a app/provider/AppServiceProvider.php donde trabajaremos en la función boot() esta función se llama cuando todos los demás service providers se hayan registrado. Una vez dentro de la misma necesitaremos utilizar view composer para registrar nuestra vista. Esto nos permitiría navegar por las rutas sin que el menú cambie su contenido. Quedaría de la siguiente manera:

public function boot()
{
   view()->composer('nav', function ($view) {
      //codigo aqui  
   });
}

Destacar que dentro del paréntesis de la función no había nada, le pusimos $view para acceder a la vista nav.

Si vemos en el navegador:

No pasa nada ya que nuestro menú esta estático todavía pero todo cambia si al utilizar la función anterior para registrar vistas le pasamos un arreglo con los nombre de los link del menú y cambiamos el contenido del fichero nav, ya verán.

En el fichero app/provider/AppServiceProvider.php creamos un arreglo con un solo elemento para probar y lo pasamos a la vista nav utilizando la función with la cual nos permite pasar elementos a las vistas, quedando de la siguiente manera:

$arr = array(
   [
        "btn" => "Link 1",
        "route" =>  "",
        "child" => NULL
   ],
);
$view->with("menu", $arr);

Note que por cada elemento del arreglo hemos creado tres variables, una para controlar el nombre del botón, la segunda para controlar la ruta o dirección del enlace y la tercera por si queremos tener un menú desplegable.

Ahora debemos modificar el contenido del fichero nav para que se adapte al arreglo que le estamos pasando, quedaría de la siguiente manera:

<nav class="navbar navbar-expand-lg navbar-light bg-light">
  
    <div class="collapse navbar-collapse">
        <ul class="navbar-nav mr-auto">
            {{-- recorremos el arreglo menu que pasamos desde el provider --}}
            @foreach ($menu as $item => $it)

                {{-- Esto funciona cuando tenemos subelementos como el dropdown --}}
                @if (is_array($it['child']) )
                    subelementos
                @else
                    {{-- si no tiene seria un link normal --}}
                    <li class="nav-item">
                        <a class="nav-link" href="/{{ $it['route'] }}">{!! $it['btn'] !!}</a>
                    </li>
                @endif

            @endforeach
        </ul>
    </div>
  </nav>

Lo que hicimos fue recorrer el arreglo que pasamos desde el provider y chequeamos las variables, en caso de que tengamos un sub-elemento se mostraría la palabra subelementos de lo contrario se mostraría el link normal.

Si chequeamos el navegador solo nos mostrara un link porque es lo que le estamos pasando por el arreglo desde el provider, el resultado sería el siguiente:

Ahora, ¿qué pasará si pasamos dos o más links?

$arr = array(
                [
                    "btn" => "Link 1",
                    "route" =>  "",
                    "child" => NULL
                ],
                [
                    "btn" => "Link 2",
                    "route" =>  "link2",
                    "child" => NULL
                ],
                [
                    "btn" => "Link 3",
                    "route" =>  "link3",
                    "child" => NULL
                ],
            );

Nos mostrará lo siguiente:

Destacar que podemos navegar entre los links ya que cuando pasamos el valor de la ruta en el arreglo se escribió la misma.

¿Qué sucede si creamos un submenú en alguno de los 3 link creados?

$arr = array(
                [
                    "btn" => "Link 1",
                    "route" =>  "",
                    "child" => NULL
                ],
                [
                    "btn" => "Link 2",
                    "route" =>  "link2",
                    "child" => NULL
                ],
                [
                    "btn" => "Mas links",
                    "child" => array(
                                        [
                                            "btn" => "Link 3",
                                            "route" =>  "link3",
                                            "child" => NULL
                                        ],
                                        [
                                            "btn" => "Link 4",
                                            "route" =>  "link4",
                                            "child" => NULL
                                        ],
                                        [
                                            "btn" => "Link 5",
                                            "route" =>  "link5",
                                            "child" => NULL
                                        ],
                                    )
                ]
            );

El resultado serían los dos link más la palabra subelementos. ¿Por qué sucede esto? porque en el fichero nav no hemos realizado la parte de los subelementos, a continuación les muestro cómo se hace.

Lo que tenemos que hacer es modificar la parte donde está el dropdown y ajustarlo a lo que le estamos pasando por el provider, quedando de la siguiente manera:

<li class="nav-item dropdown">
                        <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                            {{ $it['btn'] }}
                        </a>
                        <div class="dropdown-menu" aria-labelledby="navbarDropdown">
                            
                            @foreach ($it['child'] as $ch)
                                <a class="dropdown-item" href="/{{ $ch['route'] }}"> @lang($ch['btn']) </a>
                            
                                <div class="dropdown-divider"></div>
                            @endforeach
                        </div>
                    </li>

Si actualizamos el navegador veremos lo siguiente:

Y de este modo hemos creado un menú dinámico sin perder su funcionalidad.

El código de este ejemplo esta:

https://github.com/labrada1988/nav-dinamico.git

Please follow and like us:
error

One comment

Leave a Reply

Your email address will not be published. Required fields are marked *