DEV Community

Balaji Dharma
Balaji Dharma

Posted on • Originally published at blog.devgenius.io on

Create Reusable Blade Components in Laravel

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.

  1. Class-based components
  2. Anonymous components

The make:component Artisan command is used to create class-based components.

php artisan make:component Admin/Form/Input
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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/>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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)