Laravel cơ bản
Laravel nâng cao
Quảng cáo

Blade Template trong Laravel (2)

Trong hướng dẫn này các bạn sẽ học về layout, kế thừa view, form và validate errror trong trong Blade template

Trong bài trước chúng ta đã học về cách hiển thị dữ liệu trong Blade template và triển khai code với Blade template trong Laravel 8. Ở hướng dẫn này chúng ta sẽ đi tìm hiểu về layout, kế thừa view, form và validate error trong Blade template.

Giờ chúng ta cùng đi tìm hiểu tiếp nhé.

Nhúng view trong Blade.

@include

Blade template cho phép bạn có thể include các view khác vào trong view hiện tại một cách đơn giản bằng việc sử dụng @include directive. Lúc này ở các view được nhúng cũng có thể sử dụng được tất cả các biến có trong view hiện tại.

VD: Giả sử mình có 2 view với path và code như sau:

- resources/views/shared/notify.blade.php

Ví dụ

<div class="alert">{{ $alertMessage }}</div>

- resources/views/home.blade.php

Ví dụ

<h1>{{ $title }}</h1>
@include('shared.notify')

- routes/web.php

Ví dụ

use Illuminate\Support\Facades\Route;

Route::get('/', function () {
    return view('home', ['title' => 'VZN.vn', 'alertMessage' => 'Chào mừng bạn đến với website hướng dẫn tự học lập trình']);
})->name('home');

Kết quả: Mình sẽ để ở dạng views-source cho mọi người dễ xem.

Include view trong blade

Ở ví dụ trên trong view notify.blade.php mình đã sử dụng biến $alertMessage được truyền vào trong view home.blade.php

Trong trường hợp bạn muốn đưa thêm data vào trong view được include thì bạn có thể sử dụng cú pháp sau:

Ví dụ

@include('view.name', [$variableName => $data])

Trong đó:

  • $variableName là tên biến chưa data bạn muốn truyền vào subviews.
  • $data là giá trị của $variableName.

VD: Mình sẽ thêm alert type vào trong view notify.blade.php.

- resources/views/shared/notify.blade.php

Ví dụ

<div class="alert {{ $alertType }}">{{ $alertMessage }}</div>

- resources/views/home.blade.php

Ví dụ

<h1>{{ $title }}</h1>
@include('shared.notify', ['alertType' => 'alert-warning'])

- routes/web.php

Ví dụ

use Illuminate\Support\Facades\Route;

Route::get('/', function () {
	return view('home', ['title' => 'VZN.vn', 'alertMessage' => 'Chào mừng bạn đến với website hướng dẫn tự học lập trình']);
})->name('home');

Kết quả: Mình sẽ để ở dạng views-source cho mọi người dễ xem.

Include view trong Laravel

@includeIf

Trong blade template nếu bạn @include một view không tồn tại thì Laravel sẽ throw ra một error. Nếu bạn muốn bỏ qua exception đó thì bạn có thể dùng @includeIf. Directive này sẽ check nếu như view tồn tại thì mới thực thi việc include view.

Còn cách sử dụng thì tương tự như đối với @include.

VD: resources/views/home.blade.php

Ví dụ

<h1>{{ $title }}</h1>
@includeIf('shared.notify', ['alertType' => 'alert-warning'])

@includeWhen

Trong một số trường hợp bạn muốn kiểm tra điều kiện trước khi nhúng view thì bạn có thể sử dụng @includeWhen với cú pháp:

@includeWhen($boolean, 'view.name', $data)

Trong đó: $boolean trả về true thì view sẽ được include và ngược lại false thì view sẽ không được include.

@includeUnless

Đây là directive phủ định của @includeWhen. Nghĩa là $boolean trả về true thì view sẽ không được include và ngược lại false thì view sẽ được include.

Cú pháp:

@includeUnless($boolean, 'view.name', $data)

@includeFirst

Directive này cho phép chúng ta truyền vào một list view. Và nó sẽ kiểm tra xem nếu view nào tồn tại đầu tiên trong list thì nó sẽ nhúng view đó. Các view phía sau sẽ không được nhúng nữa.

Cú pháp:

@includeFirst(['view.name', 'view.name1', 'view.name2'], $data)

Nhúng view trong vòng lặp.

Bạn cũng có thể nhúng view qua mỗi lần lặp một mảng hay một collection trong Blade template với directive @each với cú pháp:

@each(view.name, $array, item, view.empty)

Trong đó:

  • view.name là view bạn muốn nhúng vào view hiện tại.
  • $array là mảng, collection data bạn muốn lặp.
  • item là giá trị sẽ được assign qua mỗi lần lặp.
  • view.empty là view sẽ được nhúng khi $array trống. Giá trị này có thể bỏ qua.

VD:

- resources/views/shared/post.blade.php

Ví dụ

<div class="post-item">
    <h3>{{ $post['name'] }}</h3>
</div>

- resources/views/home.blade.php

Ví dụ

<h1>List Post</h1>
<div class="list-post">
    @each('shared.post', $posts , 'post')
</div>

- routes/web.php

Ví dụ

use Illuminate\Support\Facades\Route;

Route::get('/', function () {
    $posts = [
        ['name' => 'Post 1'],
        ['name' => 'Post 2'],
        ['name' => 'Post 3'],
        ['name' => 'Post 4'],
        ['name' => 'Post 5'],
    ];

    return view('home', ['posts' => $posts]);
})->name('home');

Kết quả:

@each trong Blade template

@once

Directive này cho phép chúng ta thực thi hành động bên trong nó một lần duy nhất khi render view. Ví dụ có 2 chỗ cùng nhúng một đoạn code nếu như sử dụng directive @once thì các đoạn code phía sau once đầu tiên được thực sẽ không được thực thi nữa.

Ví dụ

@once
    @push('scripts')
        <script>
            // Your custom JavaScript...
        </script>
    @endpush
@endonce

Xây dựng layout sử dụng component trong Blade.

Hầu hết các ứng dụng web hiện này đều phân chia bố cục theo các layout riêng rồi ghép chúng lại với nhau khi cần sử dụng đến. Làm như thế khiến cho code phần view sẽ dễ đọc hơn, dễ sửa chữa thay đổi hơn.

Trong Blade template, Laravel cũng hỗ trợ chúng ta xây dựng ra các component riêng rồi nhúng nó vào khi cần dùng một cách rất đơn giản.

Định nghĩa component trong Blade template.

Để khai báo một component cơ bản trong Laravel các bạn chỉ cần khai báo chúng ở trong path resources/views/components

VD: Mình sẽ khai báo component resources/views/components/todo.blade.php.

Ví dụ

<html>
<head>
    <title>{{ $title ?? 'Todo Manager' }}</title>
</head>
<body>
<h1>VZN.vn Todos</h1>
<hr/>
{{ $slot }}
</body>
</html>

Trong đó: $slot là nơi sẽ hiện thị nội dung truyền vào component khi chúng được gọi ở view khác.

Gọi component trong Blade template

Sau khi đã khai báo được component, giờ nếu bạn muốn gọi chúng ở trong view thì có thể sử dụng cú pháp sau:

Cú pháp

<x-componentname>...</x-componentname>

// Hoặc

<x-componentname/>

Trong đó: componentname là tên file component bạn muốn gọi.

VD: Mình sẽ gọi và render component todo.blade.php ở trên.

- resources/views/home.blade.php

Ví dụ

<x-todo>
    @foreach ($tasks as $task)
        <h3>{{ $task['name'] }}</h3>
    @endforeach
</x-todo>

- routes/web.php

Ví dụ

use Illuminate\Support\Facades\Route;

Route::get('/', function () {
    $tasks = [
        ['name' => 'Task 1'],
        ['name' => 'Task 2'],
        ['name' => 'Task 3'],
        ['name' => 'Task 4'],
    ];

    return view('home', ['tasks' => $tasks]);
})->name('home');

Kết quả:

Component trong blade template

Trong một số trường hợp bạn muốn truyền data vào cho $title trong todo.blade.php thì bạn sử dụng cú pháp như sau:

Ví dụ

<x-slot name="VariableName">
    Data
</x-slot>

Trong đó:

  • VariableName là tên biến trong component bạn muốn truyền data vào.
  • Data là dữ liệu bạn muốn truyền vào.

VD: Mình sẽ bind title vào trong component todo.blade.php ở trên.

- resources/views/home.blade.php

Ví dụ

<x-todo>
    <x-slot name="title">
        Custom Title
    </x-slot>
    @foreach ($tasks as $task)
        <h3>{{ $task['name'] }}</h3>
    @endforeach
</x-todo>

Kết quả:

component trong blade template

Như các bạn đã thấy thì title đã được thay đổi.

Xây dựng layout sử dụng kế thừa trong Blade.

Ở trên chúng ta đã biết cách dựng layout với component trong Blade template rồi. Ngoài cách đó ra thì trong Blade template Laravel còn cho phép chúng ta dựng layout qua việc kế thừa các template nữa.

Định nghĩa layout

Để định nghĩa một layout trong blade các bạn có thể khai báo như bình thường.

Để cho dễ hiểu thì các bạn theo dõi ví dụ sau đây của mình rồi mình sẽ giải thích từng phần.

VD: Khai báo một layout trong resources/views/layouts/app.blade.php

Ví dụ

<html>
<head>
    <title>App Name - @yield('title')</title>
</head>
<body>
@section('sidebar')
    This is the master sidebar.
@show

<div class="container">
    @yield('content')
</div>
</body>
</html>

Trong đó:

  • @yield directive dùng để chỉ định section có name trong yield sẽ được hiển thị.
  • @section directive dùng để định nghĩa nội dung của một section.

Kế thừa layout

Sau khi đã tạo được layout rồi, để kế thừa một layout trong blade template các bạn sử dụng cú pháp:

@extends('view.name')

Trong đó: view.name là view mà bạn muốn kế thừa.

Như mình đã nói ở trên thì @section sẽ chỉ định nội dung được hiển thị @yield tương ứng trong layout.

Trong trường hợp nội dung truyền vào section là dữ liệu ngắn đơn giản thì bạn có thể sử dụng cú pháp:

Ví dụ

@section('name')

'Data Body'

@endsection

Trong đó:

  • name là tên của section bạn muốn truyền vào layout cha.
  • Data Body là dữ liệu bạn muốn truyền vào trong section.

VD: Mình sẽ khai báo một view kế thừa layout ở ví dụ trên.

- resources/views/home.blade.php

Ví dụ

@extends('layouts.app')

@section('title', 'VZN.vn Page Title')

@section('sidebar')
    @parent

    <p>This is appended to the master sidebar.</p>
@endsection

@section('content')
    <p>This is my body content.</p>
@endsection

Kết quả: (dưới dạng view-source)

Blade template trong Laravel 8

Như các bạn cũng đã thấy thì đối với @section('sidebar') mình có sử dụng directive @parent. Directive này sẽ lấy ra nội dung của @section('sidebar') trong layout cha. Nên text "This is the master sidebar." sẽ vẫn được hiển thị ra. Nếu bạn không muốn hiển thị nội dung section trong layout cha thì có thể bỏ @parent directive đi.

Trong một vài trường hợp bạn muốn xác định giá trị mặc định sẽ hiển thị khi không có data truyền vào trong @yield thì bạn có thể sử dụng cú pháp sau:

Ví dụ

@yield('name', 'Default content')

VD:

- resources/views/layouts/app.blade.php

Ví dụ

<html>
<head>
    <title>App Name - @yield('title', 'VZN.vn')</title>
</head>
<body>
@section('sidebar')
    This is the master sidebar.
@show

<div class="container">
    @yield('content')
</div>
</body>
</html>

- resources/views/home.blade.php

Ví dụ

@extends('layouts.app')

@section('sidebar')
    @parent

    <p>This is appended to the master sidebar.</p>
@endsection

@section('content')
    <p>This is my body content.</p>
@endsection

Kết quả: (dưới dạng view-source)

Blade template trong Laravel 8

Như các bạn đã thấy thì @yield('title') đã hiển thị giá trị là "VZN.vn" khi mình không khai báo section ở trong view home.blade.php

Form trong Blade template.

Trong Blade template, Laravel cũng đã cung cấp sẵn cho chúng ta một số directive hộ trợ cho việc tạo ra các method, csrf token.

Để thêm một input field hidden chứa csrf_token trong trong form các bạn có thể sử dụng directive @csrf.

Ví dụ

<form method="POST" action="/profile">
    @csrf
</form>

Kết quả: (dưới dạng view-source)

Blade template trong Laravel 8

Ngoài ra bạn có thể sử dụng directive @method để thêm một input hidden chứa method của form. Vì HTML form không thể tạo được method PUT, PATCH, DELETE.

Ví dụ

<form action="/foo/bar" method="POST">
    @method('PUT')
</form>

Kết quả: (dưới dạng view-source)

Blade template trong Laravel 8

Hiển thị validate error message trong Blade template.

Bạn có thể sử dụng @error directive để thực hiện việc hiển thị message lỗi của validation trả về (về validation mình sẽ nói ở các bài sau).

Ví dụ

<label for="title">Post Title</label>

<input id="title" type="text" class="@error('title') is-invalid @enderror">

@error('title')
    <div class="alert alert-danger">{{ $message }}</div>
@enderror

Trong đó $message là biến sẽ được assign data khi có error name là title.

Raw PHP.

Trong một số trường hợp bạn muốn sử dụng code PHP chứa logic code trong blade template bạn có thể sử dụng directive @php với cú pháp như sau:

Ví dụ

@php(// code PHP here)

// hoặc

@php

// code PHP here.

@endphp

Ví dụ

@php
    $message = "Tự học PHP";
@endphp

{{ $message }}

Bài viết này đã giúp ích cho bạn?

Advertisements