Laravel 9 Livewire JetStream CRUD Operations Tutorial

A comprehensive yet step by step Laravel Livewire CRUD (create, read, update, delete) tutorial, using the JetStream package.

I still commemorate the time when I had to go through countless hit and trial. It was indeed a tough time when I first started building a CRUD app. I have never looked back ever since I created my first CRUD application.

Today in this profound Laravel Livewire CRUD example, I will share some pearl of wisdom on how to create a CRUD in Laravel operations app using the livewire and jetstream packages.

You will see a blatant confluence of Bootstrap, Livewire, Jetstream in the Laravel ecosystem. You will learn the utter process and follow the laravel MVC (model, view, control) pattern to build a crud app.

We will create a laravel product management crud app, where you can create products, see a product list, update and delete product item. Storing the crud data into the MySQL database via a laravel app will also be taught in this guide.

How to Create Laravel 9 Livewire CRUD App using JetStream

  • Step 1: Download Laravel Project
  • Step 2: Connect to Database
  • Step 3: Create Table in Database
  • Step 4: Add Livewire in Laravel
  • Step 5: Set Up Livewire Controller
  • Step 6: Register CRUD Routes
  • Step 7: Implement CRUD in Laravel View
  • Step 8: View App on Browser

Download Laravel Project

If the Composer tool is configured, go ahead and download the latest version of the Laravel app.

composer create-project --prefer-dist laravel/laravel laravel_jetstream_crud_app

Connect to Database

In order to make the Laravel Crud app, a database connection is inevitable; append MySql database details in the .env config file.

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=db_name
DB_USERNAME=db_username
DB_PASSWORD=db_password

Create Table in Database

You have to create a migration file to create a products table into the DB; the -m attribute signifies a new model file will also be created.

php artisan make:model Product -m

Define the tables values you want to use with curd app, update database/migrations/create_products_table.php file.

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateProductsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('products', function (Blueprint $table) {
            $table->id();
            $table->string('name', 555);
            $table->string('price');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('products');
    }
}

Update app/Models/Product.php with the values you added into the migrations file.

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
    use HasFactory;
    protected $fillable = [
        'name',
        'price',
    ];
}

Add JetStream and Livewire in Laravel

Do you know most of the crud development tasks will be built on JetStream and Livewire packages, but do you know adding these quintessential libraries is an amazingly effortless and uncomplicated process?

composer require laravel/jetstream
php artisan jetstream:install livewire

Now, migration has been created, and even the Livewire scaffolding installed successfully. Go ahead execute provided commands to build assets.

npm install && npm run dev

Don’t forget to run the migration to form a tables in the database.

php artisan migrate

Set Up Livewire Controller

One of the main reasons we are using Livewire in laravel, because of its powerful and flexible ways to generate required assets dynamically.

Let’s harness the power of livewire using provided command straight from the console window.

php artisan make:livewire ProductController

Now, you have successfully created the main controller and view files.

So, update app/Http/Livewire/ProductController.php file.

<?php

namespace App\Http\Livewire;

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


class ProductController extends Component
{
    public $products, $name, $price, $mobile, $product_id;
    public $isDialogOpen = 0;

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

    public function create()
    {
        $this->resetCreateForm();
        $this->openModalPopover();
    }

    public function openModalPopover()
    {
        $this->isDialogOpen = true;
    }

    public function closeModalPopover()
    {
        $this->isDialogOpen = false;
    }

    private function resetCreateForm(){
        $this->name = '';
        $this->price = '';
    }
    
    public function store()
    {
        $this->validate([
            'name' => 'required',
            'price' => 'required',
        ]);
    
        Product::updateOrCreate(['id' => $this->product_id], [
            'name' => $this->name,
            'price' => $this->price,
        ]);

        session()->flash('message', $this->product_id ? 'Product updated!' : 'Product created!');

        $this->closeModalPopover();
        $this->resetCreateForm();
    }

    public function edit($id)
    {
        $product = Product::findOrFail($id);
        $this->product_id = $id;
        $this->name = $product->name;
        $this->price = $product->price;
    
        $this->openModalPopover();
    }
    
    public function delete($id)
    {
        Product::find($id)->delete();
        session()->flash('message', 'Product removed!');
    }    
}

Register CRUD Routes

In this step, first, open the routes/web.php, import the Livewire component, define the route method and inject the controller to set up the routes.

<?php

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

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
*/

Route::get('products', ProductController::class);

Implement CRUD in Laravel View

To create a simple crud app, you have to create and update the code in the two files, we will show a simple table and a modal popover. User can create or add a product’s name and price by opening the modal dialog, similarly that data will be displayed in the table.

Use the livewire pre-built template to create the crud app’s layout, therefore insert the code in resources/views/livewire/product-controller.blade.php file.

<x-slot name="header">
    <h2 class="text-center">Laravel JetStream Livewire CRUD Example</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-xl sm:rounded-lg px-4 py-4">
            @if (session()->has('message'))
            <div class="bg-teal-100 border-t-4 border-teal-500 rounded-b text-teal-900 px-4 py-3 shadow-md my-3"
                role="alert">
                <div class="flex">
                    <div>
                        <p class="text-sm">{{ session('message') }}</p>
                    </div>
                </div>
            </div>
            @endif
            <button wire:click="create()"
                class="bg-indigo-500 text-white font-bold py-2 px-4 rounded my-3">Add Product</button>
            @if($isDialogOpen)
            @include('livewire.create')
            @endif
            <table class="table-fixed w-full">
                <thead>
                    <tr class="bg-gray-100">
                        <th class="px-4 py-2 w-20">No.</th>
                        <th class="px-4 py-2">Name</th>
                        <th class="px-4 py-2">Price</th>
                        <th class="px-4 py-2">Action</th>
                    </tr>
                </thead>
                <tbody>
                    @foreach($products as $item)
                    <tr>
                        <td class="border px-4 py-2">{{ $item->id }}</td>
                        <td class="border px-4 py-2">{{ $item->name }}</td>
                        <td class="border px-4 py-2">{{ $item->price}}</td>
                        <td class="border px-4 py-2">
                            <button wire:click="edit({{ $item->id }})"
                                class="bg-green-700 text-white font-bold py-2 px-4">Edit</button>
                            <button wire:click="delete({{ $item->id }})"
                                class="bg-red-700 text-white font-bold py-2 px-4">Delete</button>
                        </td>
                    </tr>
                    @endforeach
                </tbody>
            </table>
        </div>
    </div>
</div>

Head over to resources/views/livewire generate a new file create.blade.php after which place the provided code into the file.

<div class="fixed z-10 inset-0 overflow-y-auto ease-out duration-400">
    <div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 sm:block sm:p-0">
        <div class="fixed inset-0 transition-opacity">
            <div class="absolute inset-0 bg-gray-500 opacity-85"></div>
        </div>
        <span class="hidden sm:inline-block sm:align-middle sm:h-screen"></span>
        <div class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full">
            <form>
                <div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
                    <div class="">
                        <div class="mb-4">
                            <input type="text" class="sshadow appearance-none border w-full" placeholder="Name" wire:model="name">
                            @error('name') <span class="text-red-500">{{ $message }}</span>@enderror
                        </div>
                        <div class="mb-4">
                            <input type="text" class="shadow appearance-none border w-full" wire:model="price"
                                placeholder="Price">
                            @error('price') <span class="text-red-500">{{ $message }}</span>@enderror
                        </div>                     
                    </div>
                </div>
                <div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
                    <span class="flex w-full rounded-md shadow-sm sm:ml-3 sm:w-auto">
                        <button wire:click.prevent="store()" type="button"
                            class="inline-flex justify-center w-full rounded-md border border-transparent px-4 py-2 bg-red-600 text-base leading-6 font-bold text-white shadow-sm hover:bg-red-700 focus:outline-none focus:border-green-700 focus:shadow-outline-green transition ease-in-out duration-150 sm:text-sm sm:leading-5">
                            Save
                        </button>
                    </span>
                    <span class="mt-3 flex w-full rounded-md shadow-sm sm:mt-0 sm:w-auto">
                        <button wire:click="closeModalPopover()" type="button"
                            class="inline-flex justify-center w-full rounded-md border border-gray-300 px-4 py-2 bg-white text-base leading-6 font-bold text-gray-700 shadow-sm hover:text-gray-700 focus:outline-none focus:border-blue-300 focus:shadow-outline-blue transition ease-in-out duration-150 sm:text-sm sm:leading-5">
                            Close
                        </button>
                    </span>
                </div>
            </form>
        </div>
    </div>
</div>

View App on Browser

You can check the Laravel Jetstream Livewire CRUD example on the browser only after running the laravel app.

php artisan serve

Ensure that you’ve successfully invoked the above command and used the below provided url.

http://127.0.0.1:8000/products

If anyhow you get error related to dashboard and navigation files, get into the files and comment all the codes located inside the following files:

# resources/views/dashboard.blade.php

# resources/views/navigation-menu.blade.php

This is only advisable for local development.

Laravel Jetstream Livewire CRUD Operations App

Conclusion

You’ve almost completed the Laravel Jetstream crud example; Livewire is not a common framework. The use of livewire allows you to build full-stack applications dynamically. Similarly, we used the livewire framework in laravel to create a faster, laravel crud app.

Furthermore, we looked at the Bootstrap CSS framework and learned how to design the crud app preciously. Eventually, the Laravel Bootstrap 5 CRUD app example is accomplished.