Laravel Blade Components — Laravel creates an admin panel from scratch — Part 12
Photo by micheile dot com on Unsplash
Blade Templates
The Blade is PHP templating engine. The Blade template allows using PHP code directly. The file extension is .blade.php and is stored in the resources/views directory
Blade is the simple, yet powerful templating engine that is included with Laravel.
Blade Components
The Blade component is similar to sections, layouts, and includes. We can create two types of components.
- Class-based components
- Anonymous components
The make:component Artisan command is used to create class-based components.
php artisan make:component Admin/Form/Input
To create an anonymous component, you may use the --view flag when invoking the make:component command.
php artisan make:component admin.form.input --view
The above command will create a Blade file at resources/views/components/admin/form/input.blade.php
Read more on the official Laravel document
Create Reusable Blade Components
We going to create some components for our admin panel. The components will reduce the number of lines in our view. Currently, our user index view file is having below code
resources/views/admin/user/index.blade.php
<x-app-layout>
<x-slot name="header">
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
{{ __('Users') }}
</h2>
</x-slot>
<div class="py-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
<div class="p-6 bg-white border-b border-gray-200">
<div class="flex flex-col mt-8">
@can('user create')
<div class="d-print-none with-border mb-8">
<a href="{{ route('user.create') }}" class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center mr-2 mb-2 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">{{ __('Add User') }}</a>
</div>
@endcan
<div class="py-2">
@if(session()->has('message'))
<div class="mb-8 text-green-400 font-bold">
{{ session()->get('message') }}
</div>
@endif
<div class="min-w-full border-b border-gray-200 shadow overflow-x-auto">
<form method="GET" action="{{ route('user.index') }}">
<div class="py-2 flex">
<div class="flex pl-2">
<input type="search" name="search" value="{{ request()->input('search') }}" class="rounded-md shadow-sm border-gray-300 focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50" placeholder="Search">
<button type='submit' class='ml-4 inline-flex items-center px-4 py-2 bg-gray-800 border border-transparent rounded-md font-semibold text-xs text-white uppercase tracking-widest hover:bg-gray-700 active:bg-gray-900 focus:outline-none focus:border-gray-900 focus:ring ring-gray-300 disabled:opacity-25 transition ease-in-out duration-150'>
{{ __('Search') }}
</button>
</div>
</div>
</form>
<table class="border-collapse table-auto w-full text-sm">
<thead>
<tr>
<th class="py-4 px-4 bg-grey-lightest font-bold uppercase text-sm text-grey-dark border-b border-grey-light text-left">
@include('admin.includes.sort-link', ['label' => 'Name', 'attribute' => 'name'])
</th>
<th class="py-4 px-4 bg-grey-lightest font-bold uppercase text-sm text-grey-dark border-b border-grey-light text-left">
@include('admin.includes.sort-link', ['label' => 'Email', 'attribute' => 'email'])
</th>
@canany(['user edit', 'user delete'])
<th class="py-4 px-4 bg-grey-lightest font-bold uppercase text-sm text-grey-dark border-b border-grey-light text-left">
{{ __('Actions') }}
</th>
@endcanany
</tr>
</thead>
<tbody class="bg-white dark:bg-slate-800">
@foreach($users as $user)
<tr>
<td class="border-b border-slate-100 dark:border-slate-700 p-4 text-slate-500 dark:text-slate-400">
<div class="text-sm text-gray-900">
<a href="{{route('user.show', $user->id)}}" class="no-underline hover:underline text-cyan-600 dark:text-cyan-400">{{ $user->name }}</a>
</div>
</td>
<td class="border-b border-slate-100 dark:border-slate-700 p-4 text-slate-500 dark:text-slate-400">
<div class="text-sm text-gray-900">
{{ $user->email }}
</div>
</td>
@canany(['user edit', 'user delete'])
<td class="border-b border-slate-100 dark:border-slate-700 p-4 text-slate-500 dark:text-slate-400">
<form action="{{ route('user.destroy', $user->id) }}" method="POST">
<div class="flex">
@can('user edit')
<a href="{{route('user.edit', $user->id)}}" class="px-4 py-2 text-white mr-4 bg-blue-600">
{{ __('Edit') }}
</a>
@endcan
@can('user delete')
@csrf
@method('DELETE')
<button class="px-4 py-2 text-white bg-red-600">
{{ __('Delete') }}
</button>
@endcan
</div>
</form>
</td>
@endcanany
</tr>
@endforeach
</tbody>
</table>
</div>
<div class="py-8">
{{ $users->appends(request()->query())->links() }}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</x-app-layout>
After creating components
<x-admin.wrapper>
<x-slot name="title">
{{ __('Users') }}
</x-slot>
@can('user create')
<x-admin.add-link href="{{ route('user.create') }}">
{{ __('Add User') }}
</x-admin.add-link>
@endcan
<div class="py-2">
<x-admin.message />
<div class="min-w-full border-b border-gray-200 shadow overflow-x-auto">
<x-admin.grid.search action="{{ route('user.index') }}" />
<x-admin.grid.table>
<x-slot name="head">
<tr>
<x-admin.grid.th>
@include('admin.includes.sort-link', ['label' => 'Name', 'attribute' => 'name'])
</x-admin.grid.th>
<x-admin.grid.th>
@include('admin.includes.sort-link', ['label' => 'Email', 'attribute' => 'email'])
</x-admin.grid.th>
@canany(['user edit', 'user delete'])
<x-admin.grid.th>
{{ __('Actions') }}
</x-admin.grid.th>
@endcanany
</tr>
</x-slot>
<x-slot name="body">
@foreach($users as $user)
<tr>
<x-admin.grid.td>
<div class="text-sm text-gray-900">
<a href="{{route('user.show', $user->id)}}" class="no-underline hover:underline text-cyan-600 dark:text-cyan-400">{{ $user->name }}</a>
</div>
</x-admin.grid.td>
<x-admin.grid.td>
<div class="text-sm text-gray-900">
{{ $user->email }}
</div>
</x-admin.grid.td>
@canany(['user edit', 'user delete'])
<x-admin.grid.td>
<form action="{{ route('user.destroy', $user->id) }}" method="POST">
<div class="flex">
@can('user edit')
<a href="{{route('user.edit', $user->id)}}" class="px-4 py-2 text-white mr-4 bg-blue-600">
{{ __('Edit') }}
</a>
@endcan
@can('user delete')
@csrf
@method('DELETE')
<button class="px-4 py-2 text-white bg-red-600">
{{ __('Delete') }}
</button>
@endcan
</div>
</form>
</x-admin.grid.td>
@endcanany
</tr>
@endforeach
</x-slot>
</x-admin.grid.table>
</div>
<div class="py-8">
{{ $users->appends(request()->query())->links() }}
</div>
</div>
</x-admin.wrapper>
We created the below components in the index.blade.php
- admin.wrapper
- admin.add-link
- admin.message
- admin.grid.search
- admin.grid.table
- admin.grid.th
- admin.grid.td
Rendering Blade Components
To render the Blade component, the tags start with the string x- followed by the kebab case name of the component class:
<x-alert/>
<x-user-profile/>
If the component class is nested deeper within the App\View\Components directory, you may use the . character to indicate directory nesting.
<x-admin.wrapper></x-admin.wrapper>
The Laravel admin panel is available on https://github.com/balajidharma/basic-laravel-admin-panel. Install the admin panel and share your feedback.
Thank you for reading.
Stay tuned for more!
Follow me at balajidharma.medium.com.
Previous part — Part 11: Restructuring a Laravel controller using Services & Action Classes
Next part — Part 13: Coming soon
Top comments (0)