The following scripts are supposed to run from your command line terminal.
mysql -u root -p
CREATE DATABASE livewire_laravel_9;
I am assuming the root user has full access to the livewire_laravel_9
database. If not, you need to assign the permissions correctly.
composer create-project laravel/laravel livewire-laravel-9
.env
to give database permissions to:DB_DATABASE=livewire_laravel_9
DB_USERNAME=root
DB_PASSWORD=root
Update your own DB_USERNAME and DB_PASSWORD accordingly.
cd livewire-laravel-9
php artisan serve
You should see the default Laravel welcome page by accessing http://127.0.0.1:8000/
from your browser:
We need some data to demonstrate the use of Datatables powered HTML table. In this step, we will create some data with minimum effort. We are going to use the default Laravel users
table as the data source.
php artisan migrate
users
table, run the command below from your terminal:php artisan tinker
User::factory()->count(20)->create();
This will create 20 records in your users
table.
composer require livewire/livewire
Create a layout file and include the Balde directives:
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" class="h-full">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{{ config('app.name', '') }}</title>
<link rel="stylesheet" href="{{ mix('css/app.css') }}">
@livewireStyles
</head>
<body>
<div class="max-w-4xl mx-auto mt-5">
<div class="px-4 sm:px-6 lg:px-8">
<h1 class="text-3xl font-black">Livewire CRUD with Laravel 9 and Tailwind CSS</h1>
</div>
</div>
{{ $slot }}
@livewireScripts
</body>
</html>
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init
webpack.mix.js
:mix.js("resources/js/app.js", "public/js")
.postCss("resources/css/app.css", "public/css", [
require("tailwindcss"),
]);
tailwind.config.js
:module.exports = {
content: [
"./resources/**/*.blade.php",
"./resources/**/*.js",
"./resources/**/*.vue",
],
theme: {
extend: {},
},
plugins: [],
}
./resources/css/app.css
:@tailwind base;
@tailwind components;
@tailwind utilities;
npm install
npm run watch
You should see a Laravel Mix message indicating successful compilation.
The ShowUsers
component is responsible for listing all users.
ShowUsers
component:php artisan make:livewire ShowUsers
Two files should be created:
app/Http/Livewire/ShowUsers.php
resources/views/livewire/show-users.blade.php
In file app/Http/Livewire/ShowUsers.php
, we simply fetch all the users
records and assign them to the view:
<?php
namespace App\Http\Livewire;
use App\Models\User;
use Livewire\Component;
class ShowUsers extends Component
{
public function render()
{
return view('livewire.show-users', [
'users' => User::all()
]);
}
}
In file resources/views/livewire/show-users.blade.php
, we loop through users
and display them in a table, make sure your Blade view only has ONE root element, this is how Livewire works:
<div class="max-w-4xl mx-auto mt-5">
<div class="px-4 sm:px-6 lg:px-8">
<div class="sm:flex sm:items-center">
<div class="sm:flex-auto">
<h1 class="text-xl font-semibold text-gray-900">Users</h1>
<p class="mt-2 text-sm text-gray-700">A list of all the users.</p>
</div>
<div class="mt-4 sm:mt-0 sm:ml-16 sm:flex-none">
<a href="/user/add"
class="inline-flex items-center justify-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 sm:w-auto">
Add user
</a>
</div>
</div>
<div class="mt-8 flex flex-col">
<div class="-my-2 -mx-4 overflow-x-auto sm:-mx-6 lg:-mx-8">
<div class="inline-block min-w-full py-2 align-middle md:px-6 lg:px-8">
<div class="overflow-hidden shadow ring-1 ring-black ring-opacity-5 md:rounded-lg">
<table class="min-w-full divide-y divide-gray-300">
<thead class="bg-gray-50">
<tr>
<th scope="col"
class="py-3 pl-4 pr-3 text-left text-xs font-medium uppercase tracking-wide text-gray-500 sm:pl-6">
ID
</th>
<th scope="col"
class="px-3 py-3 text-left text-xs font-medium uppercase tracking-wide text-gray-500">
Name
</th>
<th scope="col"
class="px-3 py-3 text-left text-xs font-medium uppercase tracking-wide text-gray-500">
Email
</th>
<th scope="col" class="relative py-3 pl-3 pr-4 sm:pr-6">
<span class="sr-only">Edit</span>
</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200 bg-white">
@foreach($users as $user)
<tr>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm font-medium text-gray-900 sm:pl-6">
{{ $user->id }}
</td>
<td class="whitespace-nowrap px-3 py-4 text-sm text-gray-500">
{{ $user->name }}
</td>
<td class="whitespace-nowrap px-3 py-4 text-sm text-gray-500">
{{ $user->email }}
</td>
<td class="relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm font-medium sm:pr-6">
<a href="/user/edit/{{ $user->id }}"
class="text-indigo-600 hover:text-indigo-900">Edit</a>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
ShowUsers
is a full page component, create a route in routes/web.php
:Route::get('/user', ShowUsers::class);
Now navigate to http://127.0.0.1:8000/user
from your browser and you should see a nice table view:
The CreateUser
component is responsible for creating a user. Which is the create
action in CRUD.
CreateUser
component:php artisan make:livewire CreateUser
Two files should be created:
app/Http/Livewire/CreateUser.php
resources/views/livewire/create-user.blade.php
In file CreateUser.php
, copy the content below:
<?php
namespace App\Http\Livewire;
use App\Models\User;
use Livewire\Component;
class CreateUser extends Component
{
public User $users ;
protected $rules = [
'users.name' => 'required|string|min:6',
'users.email' => 'required|string|max:500|unique:users',
];
public function mount()
{
$this->users = new User();
}
public function save()
{
$this->validate();
$this->users->password = time();
$this->users->save();
return redirect()->to('/user');
}
public function render()
{
return view('livewire.create-user');
}
}
User
in a public variable, this is needed for Livewire to function properly.$rules
property for us to supply some validation rules.mount
, we initialize an empty User
model for Livewire to recognize it as an Eloquent model.save
is triggered when the form is submitted, in this function, we call Livewire's validation function, followed by Eloquent's save function, and lastly we redirect the page to the index page.render
, we simply render the view file, which we are going to work on next.Open file resources/views/livewire/create-user.blade.php
and copy the content below:
<div class="max-w-4xl mx-auto mt-5">
<div class="px-4 sm:px-6 lg:px-8">
<form wire:submit.prevent="save">
<div class="mb-6">
<label for="name" class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300">Your
name</label>
<input type="text"
wire:model="users.name"
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
placeholder="Joh"
required="">
@error('users.name') <span class="text-sm text-red-500">{{ $message }}</span> @enderror
</div>
<div class="mb-6">
<label for="email" class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300">Your
email</label>
<input type="email"
wire:model="users.email"
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
placeholder="name@flowbite.com" required="">
@error('users.email') <span class="text-sm text-red-500">{{ $message }}</span> @enderror
</div>
<div class="flex items-center justify-start space-x-4">
<a href="/user" class="text-gray-900 font-medium text-sm ">Back</a>
<button type="submit"
class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm w-full sm:w-auto px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">
Save
</button>
</div>
</form>
</div>
</div>
A couple of places to take note:
<form wire:submit.prevent="save">
tells the form to call save
method of CreateUser
component.wire:model
syntax.Lastly, append the following route to routes/web.php
file:
Route::get('/user/add', CreateUser::class);
Now open your browser and head to http://127.0.0.1:8000/user/add
, you should be able to see a nicely working user creation form page:
The CreateUser
component is responsible for creating a user. Which is the create
action in CRUD.
CreateUser
component:php artisan make:livewire CreateUser
Two files should be created:
app/Http/Livewire/EditUser.php
resources/views/livewire/edit-user.blade.php
In file EditUser.php
, copy the content below:
This file is almost identical to app/Http/Livewire/CreateUser.php
, the main difference is that we have shifted the $rules
to a method instead of the original property. The reason is we need to exclude the current user id when applying the unique
rule.
Open file resources/views/livewire/edit-user.blade.php
and copy the content below:
This file is identical to resources/views/livewire/create-user.blade.php
.
Lastly, append the following route to routes/web.php
file:
Route::get('/user/edit/{user}', EditUser::class);
The {user}
declaration is the key here, by using this route, Livewire automatically helps dihydrate the model for us.
Now open your browser and head to http://127.0.0.1:8000/user
and click the Edit
link, you should be able to see a nicely working user edition form page:
One last feature missing from CRUD
actions is the Delete
. Now open file app/Http/Livewire/ShowUsers.php
and add another method:
public function delete(User $user)
{
$user->delete();
}
Open file resources/views/livewire/show-users.blade.php
and add a delete
link right after the edit
link:
<a href="#"
onclick="confirm('Are you sure you want to remove the user') || event.stopImmediatePropagation()"
wire:click="delete({{ $user->id }})"
class="text-red-600 hover:text-red-900">Delete</a>
Now open your browser and head to http://127.0.0.1:8000/user
and click the Delete
link, you should be able to delete any user:
Now head to http://127.0.0.1:8000/user
from your browser. You should see a nicely working Datatables powered HTML table:
If you follow along with the tutorial step by step, you will get all the source code in place. However, if you are feeling lazy or need to download the complete source code from us. You can do so by paying us a small fee. Your support will enable us to produce better and more in-depth tutorials.