Ir al contenido principal

Laravel 8 desde cero Parte III - Adaptando diseños (layouts), vistas (views) y estilos

 Laravel 8 desde cero Parte III  Adaptando diseños (layouts), vistas (views) y estilos

Como vimos el la parte I de esta serie de artículos sobre Laravel 8, podemos crear el proyecto con o sin autenticación, en ambos casos vamos a tener el archivo welcome.blade.php en común.
Sin embargo es al crear el proyecto con autenticación, que nos crea home.blade.php (Con el uso de Jetstream cambia por dashboard.blade.php), Views\Layouts\app.blade.php, donde Views\Layouts\ es la carpeta donde almacenaremos nuestros diseños y Public\css\app.css, donde Public\css\ es la carpeta donde almacenaremos nuestros estilos personalizados.

Rutas y controladores

En el archivo Routes\web.php, podemos ver como se define la vista raíz así:
Route::get('/', function () {
    return view('welcome');
});
Donde welcome, hace referencia al archivo Resources\Views\welcome.blade.php.
Si usamos autenticación tendremos además
Auth::routes(['verify' => true]);
Route::get('/home', [App\Http\Controllers\HomeController::class, 'index'])->name('home');
Aquí observamos dos controladores:
  • Uno declarado como Auth, que corresponde a App\Http\Controllers\Auth, carpeta donde se encuentran los controladores necesarios para servir las vistas contenidas en la carpeta Resources\Views\Auth y su subcarpeta Passwords. Lo cual simplifica todas las vistas a servir para autenticación con los controladores predeterminados para ello.
  • Dos declara la ruta /home, que corresponde a la vista del archivo home.blade.php, localizado en Resources\Views\, el cual para ser servido, esta declarado en App\Http\Controllers\HomeController.php.
De la siguiente manera:
    public function index()return view('home'); }
Vemos como la declaración de la ruta home, hace referencia al controlador (HomeController) y la función (index) que sirve o muestra en pantalla la vista home.
También observamos en HomeController la función:
public function __construct() { $this->middleware('auth'); }
La cual se encarga de exigir la autenticación para acceder a las vistas de este controlador.
Y es en el archivo App\Http\Middleware\Authenticate.php donde se declara la vista a mostrar si el usuario no ha realizado su autenticación. Por defecto redirige a la vista login.

Creando nuestros diseños (layouts)

Es en la carpeta Resources\Views\Layouts donde almacenamos las plantillas, que gracias a Laravel cuenta con recursos que con la sintaxis adecuada, permite su reutilización y fácil modificación para nuestras vistas.
Notas:
  • Lo resaltado en amarillo corresponde al contenido de los diseños o layouts.
  • Lo resaltado en verde corresponde al contenido de las vistas.
Para el ejemplo creemos en la carpeta mencionada el archivo mylayout.blade.php, con el siguiente contenido:
<!DOCTYPE html>
<html>
    <head>
        <title>@yield('title')</title>
     <link href="http://www.iconj.com/icon.php?pid=sz8zcy10pc" rel="shortcut icon" />
        <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
        <meta http-equiv="content-language" content="es" />
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
    
        <!-- CSRF Token -->
        <meta name="csrf-token" content="{{ csrf_token() }}">
        
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
<link href="{{ asset('css/mystyle.css') }}" rel="stylesheet">
    </head>
    <body>
        @include('_mynav')
        <div class="container">
        @section('mainttl')
        <h1>@lang('main.title')</h1>
        @show
        <br>    
        @yield('content')
        @section('sidebar')
            <h3>Sidebar</h3>
        @show
        </div><br>
    </body>
</html>
Podemos observar que el código anterior es muy similar a cualquier documento html, con la diferencia que se guarda como mylayout.blade.php, donde mylayout es el nombre que le asignamos a la plantilla o diseño, he resaltado ciertos detalles que explicaré a continuación y que marcan la diferencia con un documento html normal.

Analizando el contenido de la sección head

Primero que todo hay que tener en cuenta que nuestros diseños, plantillas o layouts, pueden ser usados en cualquiera de nuestras vistas, colocando el siguiente código al inicio de la vista.
@extends('layouts.mylayout')
En la sección head, he colocado dentro de la label title:
@yield('title')
Esto permite asignar un título a cada vista, o página, de la siguiente forma:
@section('title')
titulo de la  página
@endsection
Dónde "titulo de la  página", es el título que deseamos muestre la pestaña de la vista.
Si deseamos que el título se adapte al idioma lo hacemos así:
@section('title')
@lang('main.titlepg')
@endsection
Para lo cual debemos tener previamente definida la etiqueta "titlepg" en los archivos de idioma con nombre main.php, para este caso. En caso de necesitar más información sobre este tema ir a Laravel 8 desde cero Parte II.
Como vemos @yield('nombre sección'), permite personalizar su contenido en las vistas, colocando el contenido deseado dentro de:
@section('nombre sección')
contenido deseado
@endsection
Las siguientes líneas son las encargadas de evitar ataques de cierto tipo de exploits maliciosos.
<!-- CSRF Token -->
<meta name="csrf-token" content="{{ csrf_token() }}">
He resaltado esta palabra en concreto tailwindcss, que corresponde a una biblioteca de estilos, la cual a partir de Laravel 8 es necesaria para la presentación de ciertos datos, en concreto, por mi parte al usar en las vistas el código: 
{{ $posts->links() }}
Es en la carpeta public\css, donde almacenamos las personalizaciones de estilos css que deseemos, los cuales se invocan en la plantilla con el siguiente código:
{{ asset('css/mystyle.css') }}

Analizando el contenido de la sección body

La siguiente linea resaltada es:     @include('_mynav')
Esta es una característica de Laravel que nos permite escribir en un archivo aparte, el contenido de una barra de navegación o menú (o múltiples menús para múltiples plantillas), dicho archivo lo creamos en la carpeta resources\views\, con el nombre:    _mynav.blade.php
A continuación vemos el código ejemplo para la plantilla mencionada, la cual para personalizar, requiere la inclusión de los estilos o clases que definimos en: {{ asset('css/mystyle.css') }}, y que invocamos en el atributo class de los ítems, en los que deseamos una personalización determinada.
<nav class="navbar navbar-expand">
    <div class="container">
        <a class="navbar-brand" href="{{ url('/home') }}">
            <span>@lang('main.title')</span>
        </a>
        <button class="navbar-toggler custom-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="{{ __('Toggle navigation') }}">
            <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarSupportedContent">
            <!-- Right Side Of Navbar -->
            <ul class="navbar-nav ml-auto">
                <!-- Authentication Links -->
                @guest
                <li class="nav-item">
<a class="nav-link" href="{{ route('login') }}">@lang('main.lblin')</a>
                </li>
                @if (Route::has('register'))
                <li class="nav-item">
<a class="nav-link" href="{{ route('register') }}">@lang('main.lblreg')</a>
                </li>
                @endif
                @else
                <li class="nav-item dropdown">
<a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre>
                        {{ Auth::user()->name }} <span class="caret"></span>
</a>
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="navbarDropdown">
    <a class="dropdown-item" href="{{ route('logout') }}"                 
    onclick="event.preventDefault();
    document.getElementById('logout-form').submit();">
        @lang('main.lblout')
    </a>
    <form id="logout-form" action="{{ route('logout') }}" method="POST" style="display: none;">
    @csrf
    </form>
</div>
                </li>
                @endguest
            </ul>
        </div>
    </div>
</nav>
A continuación tenemos un encabezado adaptado a idiomas:
@section('mainttl')
<h1>@lang('main.title')</h1>
@show
Sin embargo dicho contenido se puede personalizar en cada vista con el siguiente código:
@section('mainttl')
<h1>Titulo</h1>
@endsection
La linea:    @yield('content')
Funciona de la misma forma que se mencionó en @yield('title'), y el código en las vistas es:
@section('content')
contenido de la vista 
@endsection
Donde el contenido de la vista va en medio de la sección declarada.
Por último en este ejemplo tenemos:
@section('sidebar')
<h3>Sidebar</h3>
@show
Sección que se puede dejar en blanco con el código siguiente en la vista.
@section('sidebar')
@endsection
O modificar con este otro código:
@section('sidebar')
Contenido deseado
@endsection
Ahora veamos como ejemplo la implementación del diseño en la vista home.blade.php
@extends('layouts.mylayout')
@section('title')
titulo de la  pagina
@endsection
@section('mainttl')
<h1>Titulo</h1>
@endsection
@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">{{ __('Dashboard') }}</div>
                <div class="card-body">
                    @if (session('status'))
                        <div class="alert alert-success" role="alert">
                            {{ session('status') }}
                        </div>
                    @endif
                    {{ __('You are logged in!') }}
                </div>
            </div>
        </div>
    </div>
</div>
@endsection
Tendremos una vista como vemos en la imagen siguiente:
Podemos observar que la pestaña muestra el texto "titulo de la  pagina", que se encuentra dentro de la @seccion('title'), la cual previamente declaramos en la plantilla base.
Si queremos que la pestaña tenga un título multi-idioma, modificamos como vimos en "Analizando el contenido de la sección head".
También podemos eliminar el texto "Titulo", simplemente dejando en blanco, el contenido entre el inicio y fin de la sección declarada en la plantilla base.
Igualmente si no queremos el texto "Sidebar", pondremos el siguiente código al final de la vista:
@section('sidebar')
@endsection

Analizando el archivo _mynav.blade.php

Lo primero que observamos es la forma como se usa el href: href="{{ url('/home') }}", básicamente en lugar de una dirección fija, hace uso de una dirección relativa y correspondiente a una vista determinada, como el anterior ejemplo hay varios resaltados que corresponden al mismo principio.
Otro detalle es el uso de @lang('main.title'), que como vimos nos permite mostrar un texto que cambia según el idioma.
Luego vemos el uso de navbarSupportedContent, el cual tiene tanto un boton como un objetivo con el id, tal cual como se hace con css y javascript.
Vemos luego @guest, que indica el inicio de la sección de invitados y que contiene el enlace al login o ingreso, a continuación con @if (Route::has('register')), indica  que si el usuario tiene que registrarse, y muestra el enlace a registro.
Luego da fin al if y abre un else que indica que si ya esta logueado o ha ingresado mostrará una barra cuyo id es: navbarDropdown, y muestra la información name del usuario ingresado y autorizado {{ Auth::user()->name }}, y al desplegar el menú del usuario vemos un enlace a logout o cerrar sesión.
El cierre de sesión utiliza javascript, para llamar al formulario que realiza el cierre de sesión, mientras protege la plataforma con @csrf, por último termina con @endguest, la sección de invitados.
Y la forma como interactúa con el usuario.
Hasta aquí la explicación de los recursos que usamos en la navbar de ejemplo.
Recuerden los conocimientos requeridos para el estudio de laravel que se detallan en Laravel 8 desde cero Parte I, los cuales son necesarios para comprender lo que no se explica ni detalla aquí, ya que se asume el conocimiento previo en dichos temas.

Con esto termino las observaciones que considero más relevantes para las vistas, diseños y estilos.
En el siguiente artículo profundizaré sobre este tema.
Les dejo también un enlace que complementa la información aquí presentada, y detalla tanto lo mencionado, como otros datos relevantes, que no incluyo aquí.


En la siguiente sección veremos como crear nuestras vistas.

Comentarios