Laravel Livewire CRUD Tutorial step by step guide

Hello Guys,

So in this post, I’ll show you a full demonstration of the Laravel livewire crud tutorial step by step. Just follow this complete livewire guide to get started.

Livewire is a full-stack framework for Laravel developers you don’t feel irritated while using livewire it’s really very simple and powerful after this livewire guide you love it like me. So are you ready let’s begin with installing Laravel

1. Install Fresh Laravel App

Now lets install the fresh and latest stable version of Laravel so we can install it by running the below command in terminal.

composer create-project --prefer-dist laravel/laravel livewire-crud-demo

2. Database setup (.env file)

After successfully installation of Laravel we need to configure our mysql database details.

DB_DATABASE=your_database_name
DB_USERNAME=your_database_username
DB_PASSWORD=your_database_password

3. Migrate Database

php artisan migrate

4. Install Livewire Package

So now we can install Laravel Livewire by running below php artisan command.

composer require livewire/livewire

Include The Assets
create a base blade file app/resources/views/layouts/app.blade.php

<html>

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="csrf-token" content="{{ csrf_token() }}">

    <title>
        @yield('title') - {{ config('app.name') }}
    </title>

    <!-- Fonts -->
    <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700&display=swap">

    <!-- Font Awesome CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"
        integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous">

    <!--  Bootstrap  -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css">

    <!-- Scripts -->
    <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"></script>

    @livewireStyles
</head>

<body>

    <div class="container mt-3">
        <div class="card">

            <!-- Page Heading -->
            <div class="card-header card text-white bg-info mb-3">
                <h5>@yield('title')</h5>
            </div>

            <!--Add main content-->
            <div class="card-body">
                {{ $slot }}
            </div>
        </div>
    </div>

    @livewireScripts
</body>

</html>

Publishing The Config File

Livewire aims for “zero-configuration” out-of-the-box, but some users require more configuration options.

You can publish Livewire’s config file with the following artisan command:

php artisan livewire:publish

5. Create a Livewire Component

So now we have done with the livewire setup and we can start using livewire componant. To create new componant we need to run below command.

php artisan make:livewire Users

generated two files by above command

  1. app/Http/Livewire/Users.php
  2. app/resources/views/livewire/users.blade.php

6. Add Route

Route::get('/users', Users::class);

Let’s begin with first file Users.php

app/Http/Livewire/Users.php

<?php

namespace App\Http\Livewire;

use App\Models\User;
use Illuminate\Validation\Rule;
use Livewire\Component;

class Users extends Component
{
    public $userId, $name, $email, $password;
    public $isUpdateMode = false;
    public $isShowMode = false;

    public function render()
    {
        return view('livewire.users', [
            'users' => User::latest()->paginate(10),
        ]);
    }

    public function enableUpdateMode()
    {
        $this->isUpdateMode = true;
        $this->resetValidation();
    }

    public function disableUpdateMode()
    {
        $this->isUpdateMode = false;
        $this->resetValidation();
        $this->resetInputFields();
    }

    private function resetInputFields()
    {
        $this->name = null;
        $this->email = null;
        $this->password = null;
        $this->userId = null;
    }

    public function edit(User $user)
    {
        $this->name = $user->name;
        $this->email = $user->email;
        $this->userId = $user->id;
        $this->enableUpdateMode();
    }

    public function store()
    {
        $validateData = $this->validate([
            'name' => 'required|string',
            'email' => 'required|string|email|unique:users',
            'password' => 'required|string|min:6',
        ]);

        User::create($validateData);

        session()->flash('success', 'User Created Successfully.');
        $this->disableUpdateMode();
    }

    public function update()
    {
        $validateData = $this->validate([
            'name' => 'required|string',
            'email' => [
                'required', 'string', 'email',
                Rule::unique('users')->ignore($this->userId),
            ],
        ]);

        User::where('id', $this->userId)
            ->update($validateData);

        session()->flash('success', 'User Updated Successfully.');
        $this->disableUpdateMode();
    }

    public function delete()
    {
        $user = User::find($this->userId);
        $user->delete();
        session()->flash('success', 'User Deleted Successfully.');
    }

}

Now open next file users.blade.php

app/resources/views/livewire/users.blade.php

@section('title', 'Users')

<div>

    @include('livewire.create')
    @include('livewire.update')

    <!-- Generic util files -->
    @include('layouts.util.flash-msg')
    @include('layouts.util.delete-confirm')
    @include('layouts.util.loading')

    <!-- Table Data-->
    <div class="table-responsive">
        <table class="table table-bordered">
            <thead>
                <tr class="table-success">
                    <th>Id.</th>
                    <th>Name</th>
                    <th>Email</th>
                    <th>Joining_time</th>
                    <th>Action</th>
                </tr>
            </thead>
            <tbody>
                @foreach ($users as $value)
                <tr>
                    <td>{{ $value->id }}</td>
                    <td>{{ $value->name }}</td>
                    <td>{{ $value->email }}</td>
                    <td>{{ $value->created_at }}</td>
                    <td>
                        <div class="d-inline-flex">
                            <button class="btn btn-primary" wire:click="edit({{ $value->id }})">
                                <i class="fa fa-edit"></i>
                            </button>

                            <button data-toggle="modal" data-target="#deleteModal"
                                wire:click="$set('userId', '{{$value->id}}')" class="btn btn-danger ml-1">
                                <i class="fa fa-trash"></i>
                            </button>
                        </div>
                    </td>
                </tr>
                @endforeach
            </tbody>
        </table>
    </div>

    {{-- Pagination --}}
    {!! $users->links() !!}
</div>

Now we need to create 5 more blade files
views/livewire/create.blade.php
views/livewire/update.blade.php


views/layouts/util/delete-confirm.blade.php
views/layouts/util/flash.msg.blade.php
views/layouts/util/loading.blade.php

…/views/livewire/create.blade.php

@if (!$isUpdateMode)

<form wire:submit.prevent="store">
    <div class="form-row">
        <div class="form-group col-md-4">
            <label for="name">Name</label>
            <input id='name' type="text" wire:model.defer='name' class='form-control'>
            @error('name')<span class="text-danger">{{ $message ?: '' }}</span>@enderror
        </div>
        <div class="form-group col-md-4">
            <label for="email">Email</label>
            <input id='email' type="text" wire:model.defer='email' class='form-control'>
            @error('email')<span class="text-danger">{{ $message ?: '' }}</span>@enderror
        </div>
        <div class="form-group col-md-4">
            <label for="password">Password</label>
            <input id='password' type="password" wire:model.defer='password' class='form-control'>
            @error('password')<span class="text-danger">{{ $message ?: '' }}</span>@enderror
        </div>
    </div>
    <button class="btn btn-primary">Add</button>
</form>
@endif

This file will handle new user creation

…/views/livewire/update.blade.php

@if ($isUpdateMode)
<form wire:submit.prevent="update" class="mb-4">

    <div class="form-row">
        <div class="form-group col-md-6">
            <label for="name">Name</label>
            <input id='name' type="text" wire:model.defer='name' class='form-control'>
            @error('name')<span class="text-danger">{{ $message ?: '' }}</span>@enderror
        </div>

        <div class="form-group col-md-6">
            <label for="email">Email</label>
            <input id='email' type="text" wire:model.defer='email' class='form-control'>
            @error('email')<span class="text-danger">{{ $message ?: '' }}</span>@enderror
        </div>
    </div>

    <button class="btn btn-primary">Update</button>
    <button wire:click.prevent="closeModal" class="btn btn-secondary" type="button">Close</button>
</form>
@endif


this file is responsible for user update

Now lets create util files.

…/views/layouts/util/delete-confirm.blade.php

  <div wire:ignore.self id="deleteModal" class="modal fade" tabindex="-1" role="dialog"
      aria-labelledby="deleteModalLabel" aria-hidden="true">

      <div class="modal-dialog modal-dialog-centered" role="document">
          <div class="modal-content">

              <div class="modal-header">
                  <h5 class="modal-title" id="exampleModalLabel">
                      Are you sure you want to delete?
                  </h5>
                  <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                      <span aria-hidden="true">×</span>
                  </button>
              </div>
              <div class="modal-footer">
                  @if (method_exists($this, 'closeModal'))
                  <button type="button" class="btn btn-secondary close-btn" wire:click.prevent="closeModal"
                      data-dismiss="modal">No</button>
                  @else
                  <button type="button" class="btn btn-secondary close-btn" data-dismiss="modal">No</button>
                  @endif

                  <button type="button" wire:click.prevent="delete" class="btn btn-danger close-modal"
                      data-dismiss="modal">
                      Delete
                  </button>
              </div>
          </div>
      </div>
  </div>

…/views/layouts/util/flash-msg.blade.php

<div id="messages">
    @if(session()->has('success'))
    <div class="alert alert-success alert-dismissible fade show">
        <button type="button" class="close" data-dismiss="alert">×</button>
        <div class="row">
            <div class="col-12">{{ session('success') }}</div>
        </div>
    </div>

    @elseif(session()->has('error'))
    <div class="alert alert-danger alert-dismissible fade show">
        <button type="button" class="close" data-dismiss="alert">×</button>
        <div class="row">
            <div class="col-12">{{ session('error') }}</div>
        </div>
    </div>
    @endif
</div>

…/views/layouts/util/loading.blade.php

<div wire:loading wire:target="store,edit,delete,update,delete" class="full-width-div">
    <div class="content_center">
        <div class="spinner-border text-light" role="status"></div>
    </div>
</div>

<style>
    .content_center {
        position: fixed;
        display: flex;
        justify-content: center;
        align-items: center;
        width: 100%;
        height: 100%;
    }

    .full-width-div {
        width: 100%;
        height: 100%;
        top: -22px;
        left: -22px;
        margin-top: 22px;
        margin-left: 22px;
        background: rgba(0, 0, 0, 0.5);
        position: fixed;
    }

</style>

You can use this loading overlay anywhere in your project just by including it.

Now everything is Done!

It’s time to tet our newly created Laravel livewire App So what you need to do now.

Just run below command to start your php server.

php artian serve

Now your server is running mode you go http://127.0.0.1:8000/users

Great you have done it!!

Now it’ time to share this article.

FAQ

  1. Can I Livewire without Jetstream?

    Yes you can use it because both are totally differnet packages livewire just like Vue.js and react.

One Comment

Leave a Reply

Your email address will not be published. Required fields are marked *