CRUD Operations Using Laravel Livewire 3

Laravel Livewire 3 is a powerful framework for building dynamic interfaces directly in Laravel. It allows you to create, read, update, and delete (CRUD) operations with minimal effort, combining the power of Laravel with the reactivity of modern JavaScript frameworks. In this article, we'll explore how to implement CRUD operations using Laravel Livewire 3.


Getting Started


Before we dive into CRUD operations, let's set up a new Laravel project and install Livewire.


1. Create a new Laravel project:


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

   cd livewire-crud


2. Install Livewire:


   composer require livewire/livewire


3. Publish Livewire assets:


   php artisan livewire:publish


4. Set up a database:


   Configure your `.env` file to connect to your database.


5. Run migrations:


   php artisan migrate


Creating the Model and Migration


For this example, we'll create a simple `Post` model with `title` and `content` fields.


1. Create the model and migration:


   php artisan make:model Post -m


2. Define the `posts` table schema in the migration file:


   // database/migrations/xxxx_xx_xx_create_posts_table.php


   public function up()

   {

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

           $table->id();

           $table->string('title');

           $table->text('content');

           $table->timestamps();

       });

   }


3. Run the migration:


   php artisan migrate


Setting Up Livewire Components


Livewire components are where we’ll handle the CRUD operations. Let’s create a Livewire component for managing posts.


1. Create the Livewire component:


   php artisan make:livewire PostManager


2. Define the component logic in `PostManager.php`:


   // app/Http/Livewire/PostManager.php


   namespace App\Http\Livewire;


   use Livewire\Component;

   use App\Models\Post;


   class PostManager extends Component

   {

       public $posts, $title, $content, $post_id;

       public $isOpen = 0;


       public function render()

       {

           $this->posts = Post::all();

           return view('livewire.post-manager');

       }


       public function create()

       {

           $this->resetInputFields();

           $this->openModal();

       }


       public function openModal()

       {

           $this->isOpen = true;

       }


       public function closeModal()

       {

           $this->isOpen = false;

       }


       private function resetInputFields()

       {

           $this->title = '';

           $this->content = '';

           $this->post_id = '';

       }


       public function store()

       {

           $this->validate([

               'title' => 'required',

               'content' => 'required',

           ]);


           Post::updateOrCreate(['id' => $this->post_id], [

               'title' => $this->title,

               'content' => $this->content,

           ]);


           session()->flash('message',

               $this->post_id ? 'Post Updated Successfully.' : 'Post Created Successfully.');


           $this->closeModal();

           $this->resetInputFields();

       }


       public function edit($id)

       {

           $post = Post::findOrFail($id);

           $this->post_id = $id;

           $this->title = $post->title;

           $this->content = $post->content;


           $this->openModal();

       }


       public function delete($id)

       {

           Post::find($id)->delete();

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

       }

   }


3. Create the component view in `resources/views/livewire/post-manager.blade.php`:


   <div>

       <button wire:click="create()" class="btn btn-primary">Create Post</button>


       @if($isOpen)

           @include('livewire.create')

       @endif


       <table class="table table-bordered mt-5">

           <thead>

               <tr>

                   <th>No.</th>

                   <th>Title</th>

                   <th>Content</th>

                   <th>Action</th>

               </tr>

           </thead>

           <tbody>

               @foreach($posts as $post)

               <tr>

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

                   <td>{{ $post->title }}</td>

                   <td>{{ $post->content }}</td>

                   <td>

                       <button wire:click="edit({{ $post->id }})" class="btn btn-primary">Edit</button>

                       <button wire:click="delete({{ $post->id }})" class="btn btn-danger">Delete</button>

                   </td>

               </tr>

               @endforeach

           </tbody>

       </table>

   </div>


4. Create the modal view in `resources/views/livewire/create.blade.php`:


   <div class="fixed z-10 inset-0 overflow-y-auto ease-out duration-400">

       <div class="flex justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">

           <div class="fixed inset-0 transition-opacity">

               <div class="absolute inset-0 bg-gray-500 opacity-75"></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" role="dialog" aria-modal="true" aria-labelledby="modal-headline">

               <form>

                   <div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">

                       <div class="">


                           <div class="mb-4">

                               <label for="title" class="block text-gray-700 text-sm font-bold mb-2">Title:</label>

                               <input type="text" id="title" wire:model="title" class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline">

                               @error('title') <span class="text-red-500">{{ $message }}</span>@enderror

                           </div>


                           <div class="mb-4">

                               <label for="content" class="block text-gray-700 text-sm font-bold mb-2">Content:</label>

                               <textarea id="content" wire:model="content" class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"></textarea>

                               @error('content') <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="mt-3 flex w-full rounded-md shadow-sm sm:mt-0 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-blue-500 text-base leading-6 font-medium text-white shadow-sm hover:bg-blue-400 focus:outline-none focus:border-blue-700 focus:shadow-outline-blue 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="closeModal()" 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-medium text-gray-700 shadow-sm hover:text-gray-500 focus:outline-none focus:border-blue-300 focus:shadow-outline-blue transition ease-in-out duration-150 sm:text-sm sm:leading-5">

                             Cancel

                           </button>

                       </span>

                   </div>

               </form>

           </div>

       </div>

   </div>


5. Include the Livewire component in your main view:


   // resources/views/welcome.blade.php


   <!DOCTYPE html>

   <html>

   <head>

       <title>Laravel Livewire CRUD</title>

       <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/2.0.3/tailwind.min.css">

       @livewireStyles

   </head>

   <body>

       <div class="container mx-auto">

           <h1 class="text-4xl my-8 text-center">Laravel Livewire CRUD</h1>

           @livewire('post-manager')

       </div>

       @livewireScripts

   </body>

   </html>



By leveraging Livewire, we can create dynamic, reactive applications without writing much JavaScript. This approach not only simplifies the development process but also maintains the power and flexibility of Laravel. With these steps, you can start building your own CRUD applications using Laravel Livewire 3.