Livewire : CRUD Tutorial in Laravel

Kaushik ThakkarKaushik Thakkar
5 min read

Laravel Livewire is a library that allows you to build dynamic, reactive user interfaces in Laravel using a simple, component-based approach. In this tutorial, we'll create a basic CRUD (Create, Read, Update, Delete) application using Laravel Livewire.

Prerequisites

Before we begin, you should have the following installed on your system:

  • PHP 7.4 or later

  • Laravel 8 or later

  • Composer

  • Node.js

  • NPM

Before we get started, you'll need to make sure you have Laravel installed on your system. You can install Laravel using Composer by running the following command:

composer global require laravel/installer

Once you have Laravel installed, you can create a new Laravel project by running the following command:

laravel new project-name

After the project is created, navigate to the project directory and run the following command to install Livewire:

composer require livewire/livewire

Creating the Model

First, we'll create a Product model that we'll use to store our product data. Run the following command to create the model:

php artisan make:model Product -m

The -m option will create a migration file for the model.

Next, open the migration file located in database/migrations and add the following columns to the up method:

$table->id();
$table->string('name');
$table->text('description');
$table->integer('price');
$table->timestamps();

Once you have added the columns, run the migration to create the products table in your database:

php artisan migrate

Creating the Livewire Component

Next, we'll create a Livewire component that will handle the creation, reading, updating, and deleting of products. Run the following command to create the component:

php artisan make:livewire Products

This will create a Products class in the app/Http/Livewire directory. Open the Products class and add the following code:

namespace App\Http\Livewire;

use Livewire\Component;
use App\Models\Product;

class Products extends Component
{
    public $products, $name, $description, $price, $product_id;
    public $isOpen = 0;

    public function render()
    {
        $this->products = Product::all();
        return view('livewire.products.index');
    }

    public function create()
    {
        $this->resetInputFields();
        $this->openModal();
    }

    public function openModal()
    {
        $this->isOpen = true;
    }

    public function closeModal()
    {
        $this->isOpen = false;
    }

    private function resetInputFields(){
        $this->name = '';
        $this->description = '';
        $this->price = '';
        $this->product_id = '';
    }

    public function store()
    {
        $this->validate([
            'name' => 'required',
            'description' => 'required',
            'price' => 'required',
        ]);

        Product::create([
            'name' => $this->name,
            'description' => $this->description,
            'price' => $this->price,
        ]);

        $this->closeModal();
        $this->resetInputFields();
    }

    public function edit($id)
    {
        $product = Product::findOrFail($id);
        $this->product_id = $id;
        $this->name = $product->name;
        $this->description = $product->description;
        $this->price = $product->price;

        $this->openModal();
    }

    public function update()
    {
        $this->validate([
            'name' => 'required',
            'description' => 'required',
            'price' => 'required',
        ]);

        $product = Product::find($this->product_id);
        $product->update([
            'name' => $this->name,
            'description' => $this->description,
            'price' => $this->price,
        ]);

        $this->closeModal();
        $this->resetInputFields();
    }

    public function delete($id)
    {
        Product::find($id)->delete();
    }
}

In this code, we're defining some public properties that we'll use to store data, as well as the render method which will return the Livewire view that we'll create later. We're also using the Product model that we created earlier to retrieve all of the products from the database.

Creating the View

Next, we'll create a Livewire view that will display our products and allow us to add, edit, and delete products. Create a new file called index.blade.php in the resources/views/livewire/products directory, and add the following code:

<div>
    @if($isOpen)
        @include('livewire.products.create')
    @endif
    <button wire:click="create()" class="btn btn-primary mb-3">Add Product</button>
    <table class="table">
        <thead>
            <tr>
                <th>ID</th>
                <th>Name</th>
                <th>Description</th>
                <th>Price</th>
                <th>Action</th>
            </tr>
        </thead>
        <tbody>
            @foreach($products as $product)
                <tr>
                    <td>{{ $product->id }}</td>
                    <td>{{ $product->name }}</td>
                    <td>{{ $product->description }}</td>
                    <td>{{ $product->price }}</td>
                    <td>
                        <button wire:click="edit({{ $product->id }})" class="btn btn-primary btn-sm">Edit</button>
                        <button wire:click="delete({{ $product->id }})" class="btn btn-danger btn-sm">Delete</button>
                    </td>
                </tr>
            @endforeach
        </tbody>
    </table>
</div>

In this code, we're displaying a table of products, with an "Add Product" button that will open a modal dialog when clicked. We're also using Livewire directives to wire up the "Edit" and "Delete" buttons to their respective methods on the Products class.

Creating the Modal

Finally, we'll create the modal dialog that will allow us to add and edit products. Create a new file called modal.blade.php in the resources/views/livewire/products directory, and add the following code:

<div class="modal fade" wire:ignore.self id="createModal" tabindex="-1" role="dialog" aria-labelledby="createModalLabel" aria-hidden="true">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title" id="createModalLabel">Add Product</h5>
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">&times;</span>
                </button>
            </div>
            <div class="modal-body">
                <form>
                    <div class="form-group">
                        <label for="name">Name</label>
                        <input type="text" class="form-control" id="name" wire:model="name" placeholder="Enter name">
                        @error('name') <span class="text-danger">{{ $message }}</span>@enderror
                    </div>
                    <div class="form-group">
                        <label for="description">Description</label>
                        <textarea class="form-control" id="description" wire:model="description" placeholder="Enter description"></textarea>
                        @error('description') <span class="text-danger">{{ $message }}</span>@enderror
                    </div>
                    <div class="form-group">
                        <label for="price">Price</label>
                        <input type="text" class="form-control" id="price" wire:model="price" placeholder="Enter price">
                        @error('price') <span class="text-danger">{{ $message }}</span>@enderror
                    </div>
                </form>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
                <button wire:click.prevent="store()" type="button" class="btn btn-primary">Save</button>
            </div>
        </div>
    </div>
</div>

This file defines a modal form that is used to create a new product. It includes three input fields for the name, description, and price of the product, along with error messages that will be displayed if the user submits invalid data. It also includes buttons to close the modal and save the new product.

Updating the Routes

Now that we have the component and views set up, we need to update the routes to point to the Products component. Open the web.php file and update it with the following code:

<?php

use Illuminate\Support\Facades\Route;
use App\Http\Livewire\Products;

Route::get('/', Products::class);

This code sets up the default route to display the Products component when the user visits the homepage.

Testing the Application

We're now ready to test our CRUD application! Start the development server by running the following command in your terminal:

php artisan serve

Then open your browser and go to http://localhost:8000. You should see a table with all the products listed.

To add a new product, click the "Add Product" button, fill out the form, and click the "Save" button. The new product should be added to the table.

To edit an existing product, click the "Edit" button next to the product you want to edit, make your changes in the modal form, and click the "Save" button.

0
Subscribe to my newsletter

Read articles from Kaushik Thakkar directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Kaushik Thakkar
Kaushik Thakkar

I’m Kaushik, enjoy learning and writing about my experience, Full stack developer from India. Experecened in Laravel, PHP, CodeIgniter, WordPress,JavaScript, jQuery, Bootstrap and REST API.