Laravel 9 Livewire CRUD using Bootstrap Modal

Submitted by admin@soz on Wed, 04/13/2022 - 23:13

Laravel 9 Livewire CRUD using Bootstrap Modal with Pagination, Search bar & Validation in Livewire

Step 1: Setup the Laravel 9 Project:

composer create-project laravel/laravel laravel9Livewire

Step 2: Connect Database in .env file:

DB_CONNECTION=mysql
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=students
DB_USERNAME=root
DB_PASSWORD=

Step 2.1: Open phpmyadmin & create database name 'students'

Step 3: Create Model, Migration, and Controller for student details:

Modal: Creating Model for Student with the following command:

php artisan make:model Student

 after successfully creating student model (App/Models/Student.php), paste the below code:

<?php

namespace App\Models; 

use Illuminate\Database\Eloquent\Factories\HasFactory;

use Illuminate\Database\Eloquent\Model;

class Student extends Model

{

    use HasFactory;

    protected $table = 'students';

    protected $fillable = [

        'name',

        'email',

        'course',

    ];

}

Migration: Creating Migration for Student with the following command:

php artisan make:migration create_students_table 

After successfully creating table, go to database/migrations/..create_students_table.php and update 'public function up()' with the following code 

public function up()

{

    Schema::create('students', function (Blueprint $table) {

        $table->id();

        $table->string('name');

        $table->string('email');

        $table->string('course');

        $table->timestamps();

    });

}

Let's Migrate the tables with following command:

php artisan migrate 

Controller: Creating Controller for Student with the following command:

php artisan make:controller StudentController 

Go to app/Http/Controllers/StudentController.php and update with the following code

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class StudentController extends Controller

{

    public function index()

    {

        return view('student.index');

    }

}

Step 4: Install Livewire in Laravel with the following command:

composer require livewire/livewire 

Step 5: Install Auth Scaffolding with the following command:

composer require laravel/ui 

php artisan ui:auth 

Step 6: Include livewire Assets and add bootstrap cdn link in the following path: resources/views/layouts/app.blade.php

<!doctype html>

<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">

<head>

    <meta charset="utf-8">

    <meta name="viewport" content="width=device-width, initial-scale=1">

    <meta name="csrf-token" content="{{ csrf_token() }}">
...

    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">

    @livewireStyles 

</head>

<body>
....

    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>

    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.m…"></script>

    @livewireScripts

    @yield('script')

</body>

</html>

Step 7: Let's create Student Livewire component with the following command:

php artisan make:livewire StudentShow 

after successfully creating the Student Livewire component, you see two files in app folder and resources folder.

CLASS: app/Http/Livewire/StudentShow.php

VIEW:  resources/views/livewire/student-show.blade.php

Step 8: go to livewire component in the following path: app/http/livewire/StudentShow.php and paste the below code:

<?php

namespace App\Http\Livewire;

use Livewire\WithPagination;

use App\Models\Student;

use Livewire\Component;

class StudentShow extends Component

{

    use WithPagination;

    protected $paginationTheme = 'bootstrap'; 

    public $name, $email, $course, $student_id;

    public $search = '';

    protected function rules()

    {

        return [

            'name' => 'required|string|min:6',

            'email' => ['required','email'],

            'course' => 'required|string',

        ];

    } 

    public function updated($fields)

    {

        $this->validateOnly($fields);

    }

    public function saveStudent()

    {

        $validatedData = $this->validate();

        Student::create($validatedData);

        session()->flash('message','Student Added Successfully');

        $this->resetInput();

        $this->dispatchBrowserEvent('close-modal');

    } 

    public function editStudent(int $student_id)

    {

        $student = Student::find($student_id);

        if($student){ 

            $this->student_id = $student->id;

            $this->name = $student->name;

            $this->email = $student->email;

            $this->course = $student->course;

        }else{

            return redirect()->to('/students');

        }

    }

    public function updateStudent()

    {

        $validatedData = $this->validate();

        Student::where('id',$this->student_id)->update([

            'name' => $validatedData['name'],

            'email' => $validatedData['email'],

            'course' => $validatedData['course']

        ]);

        session()->flash('message','Student Updated Successfully');

        $this->resetInput();

        $this->dispatchBrowserEvent('close-modal');

    }

    public function deleteStudent(int $student_id)

    {

        $this->student_id = $student_id;

    } 

    public function destroyStudent()

    {

        Student::find($this->student_id)->delete();

        session()->flash('message','Student Deleted Successfully');

        $this->dispatchBrowserEvent('close-modal');

    }

    public function closeModal()

    {

        $this->resetInput();

    }

    public function resetInput()

    {

        $this->name = '';

        $this->email = '';

        $this->course = '';

    }

    public function render()

    {

        $students = Student::where('name', 'like', '%'.$this->search.'%')->orderBy('id','DESC')->paginate(3);

        return view('livewire.student-show', ['students' => $students]);

    }

}

Step 9:  Go to livewire blade view in the following path: resources/views/livewire/student-show.blade.php and paste the below code:

<div>

    @include('livewire.studentmodal')

    <div class="container">

        <div class="row">

            <div class="col-md-12">

                @if (session()->has('message'))

                    <h5 class="alert alert-success">{{ session('message') }}</h5>

                @endif 

                <div class="card">

                    <div class="card-header">

                        <h4>Student CRUD with Bootstrap Modal

                            <input type="search" wire:model="search" class="form-control float-end mx-2" placeholder="Search..." style="width: 230px" />

                            <button type="button" class="btn btn-primary float-end" data-bs-toggle="modal" data-bs-target="#studentModal">

                                Add New Student

                            </button>

                        </h4>

                    </div>

                    <div class="card-body">

                        <table class="table table-borderd table-striped">

                            <thead>

                                <tr>

                                    <th>ID</th>

                                    <th>Name</th>

                                    <th>Email</th>

                                    <th>Course</th>

                                    <th>Actions</th>

                                </tr>

                            </thead>

                            <tbody>

                                @forelse ($students as $student)

                                    <tr>

                                        <td>{{ $student->id }}</td>

                                        <td>{{ $student->name }}</td>

                                        <td>{{ $student->email }}</td>

                                        <td>{{ $student->course }}</td>

                                        <td>

                                            <button type="button" data-bs-toggle="modal" data-bs-target="#updateStudentModal" wire:click="editStudent({{$student->id}})" class="btn btn-primary">

                                                Edit

                                            </button>

                                            <button type="button" data-bs-toggle="modal" data-bs-target="#deleteStudentModal" wire:click="deleteStudent({{$student->id}})" class="btn btn-danger">Delete</button>

                                        </td>

                                    </tr>

                                @empty

                                    <tr>

                                        <td colspan="5">No Record Found</td>

                                    </tr>

                                @endforelse

                            </tbody>

                        </table>

                        <div>

                            {{ $students->links() }}

                        </div>

                    </div>

                </div>

            </div>

        </div>

    </div>

</div>

now, create another file in same folder: resources/views/livewire/ named studentmodal.blade.php which we included in the above file.

<!-- Insert Modal -->

<div wire:ignore.self class="modal fade" id="studentModal" tabindex="-1" aria-labelledby="studentModalLabel"

    aria-hidden="true">

    <div class="modal-dialog">

        <div class="modal-content">

            <div class="modal-header">

                <h5 class="modal-title" id="studentModalLabel">Create Student</h5>

                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"

                    wire:click="closeModal"></button>

            </div>

            <form wire:submit.prevent="saveStudent">

                <div class="modal-body">

                    <div class="mb-3">

                        <label>Student Name</label>

                        <input type="text" wire:model="name" class="form-control">

                        @error('name') <span class="text-danger">{{ $message }}</span> @enderror

                    </div>

                    <div class="mb-3">

                        <label>Student Email</label>

                        <input type="text" wire:model="email" class="form-control">

                        @error('email') <span class="text-danger">{{ $message }}</span> @enderror

                    </div>

                    <div class="mb-3">

                        <label>Student Course</label>

                        <input type="text" wire:model="course" class="form-control">

                        @error('course') <span class="text-danger">{{ $message }}</span> @enderror

                    </div>

                </div>

                <div class="modal-footer">

                    <button type="button" class="btn btn-secondary" wire:click="closeModal"

                        data-bs-dismiss="modal">Close</button>

                    <button type="submit" class="btn btn-primary">Save</button>

                </div>

            </form>

        </div>

    </div>

</div>

 

<!-- Update Student Modal -->

<div wire:ignore.self class="modal fade" id="updateStudentModal" tabindex="-1" aria-labelledby="updateStudentModalLabel"

    aria-hidden="true">

    <div class="modal-dialog">

        <div class="modal-content">

            <div class="modal-header">

                <h5 class="modal-title" id="updateStudentModalLabel">Edit Student</h5>

                <button type="button" class="btn-close" data-bs-dismiss="modal" wire:click="closeModal"

                    aria-label="Close"></button>

            </div>

            <form wire:submit.prevent="updateStudent">

                <div class="modal-body">

                    <div class="mb-3">

                        <label>Student Name</label>

                        <input type="text" wire:model="name" class="form-control">

                        @error('name') <span class="text-danger">{{ $message }}</span> @enderror

                    </div>

                    <div class="mb-3">

                        <label>Student Email</label>

                        <input type="text" wire:model="email" class="form-control">

                        @error('email') <span class="text-danger">{{ $message }}</span> @enderror

                    </div>

                    <div class="mb-3">

                        <label>Student Course</label>

                        <input type="text" wire:model="course" class="form-control">

                        @error('course') <span class="text-danger">{{ $message }}</span> @enderror

                    </div>

                </div>

                <div class="modal-footer">

                    <button type="button" class="btn btn-secondary" wire:click="closeModal"

                        data-bs-dismiss="modal">Close</button>

                    <button type="submit" class="btn btn-primary">Update</button>

                </div>

            </form>

        </div>

    </div>

</div>

 

<!-- Delete Student Modal -->

<div wire:ignore.self class="modal fade" id="deleteStudentModal" tabindex="-1" aria-labelledby="deleteStudentModalLabel"

    aria-hidden="true">

    <div class="modal-dialog">

        <div class="modal-content">

            <div class="modal-header">

                <h5 class="modal-title" id="deleteStudentModalLabel">Delete Student</h5>

                <button type="button" class="btn-close" data-bs-dismiss="modal" wire:click="closeModal"

                    aria-label="Close"></button>

            </div>

            <form wire:submit.prevent="destroyStudent">

                <div class="modal-body">

                    <h4>Are you sure you want to delete this data ?</h4>

                </div>

                <div class="modal-footer">

                    <button type="button" class="btn btn-secondary" wire:click="closeModal"

                        data-bs-dismiss="modal">Close</button>

                    <button type="submit" class="btn btn-primary">Yes! Delete</button>

                </div>

            </form>

        </div>

    </div>

</div>

 

Step 10: So now guys, let's include the livewire component data in blade file by calling with livewire syntax: Create folder name 'student' and create file name 'index.blade.php' into 'student' folder (resources/views/student/index.blade.php) this file is coming from your StudentController. 

@extends('layouts.app')

 

@section('content')

 

    <div>

        <livewire:student-show>

    </div>

 

@endsection

 

@section('script')

<script>

    window.addEventListener('close-modal', event => {

 

        $('#studentModal').modal('hide');

        $('#updateStudentModal').modal('hide');

        $('#deleteStudentModal').modal('hide');

    })

</script>

@endsection

 

Start the server:

php artisan serve 

Finish..

Credit to (oroginal source): https://www.fundaofwebit.com/post/laravel-9-livewire-crud-using-bootstr…;