Laravel Livewire Crud

Laravel Livewire Crud

Hello there guys! in this post, we will be looking at Laravel Livewire Crud operations by implementing them on a blog. Let’s get started.

Step 1: Installing Laravel and Livewire

To get started with creating a blog using Laravel Livewire, we first need to have Laravel installed on our machine. To do this, we will be using the Composer package manager. Make sure you have Composer installed on your machine by running the command composer -v in your terminal. If you do not have Composer installed, you can download it from the official website.

Once you have Composer installed, navigate to the directory where you want to create your project and run the command composer create-project laravel/laravel blog to create a new Laravel project. Next, we will install Livewire by running the command composer require livewire/livewire in the project directory.

Step 2: Creating a Livewire Component

Now that we have Laravel and Livewire installed, we can start creating our Livewire component for the blog. In the command line, navigate to the project directory and run the command php artisan make:livewire posts. This will create a new Livewire component called “posts” in the “app/Http/Livewire” directory. Open the “posts.php” file located in “app/Http/Livewire” and you will see that it has a basic structure for a Livewire component. This is where we will be adding the logic for our blog.

app/Http/Livewire/posts.php

<?php

namespace App\Http\Livewire;

use Livewire\Component;
use App\Models\Post as Posts;

class Post extends Component
{
    public $posts, $title, $description, $postId, $updatePost = false, $addPost = false;
 
    /**
     * delete action listener
     */
    protected $listeners = [
        'deletePostListner'=>'deletePost'
    ];
 
    /**
     * List of add/edit form rules
     */
    protected $rules = [
        'title' => 'required',
        'description' => 'required'
    ];
 
    /**
     * Reseting all inputted fields
     * @return void
     */
    public function resetFields(){
        $this->title = '';
        $this->description = '';
    }
 
    /**
     * render the post data
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
     */
    public function render()
    {
        $this->posts = Posts::select('id', 'title', 'description')->get();
        return view('livewire.posts');
    }
 
    /**
     * Open Add Post form
     * @return void
     */
    public function addPost()
    {
        $this->resetFields();
        $this->addPost = true;
        $this->updatePost = false;
    }
     /**
      * store the user inputted post data in the posts table
      * @return void
      */
    public function storePost()
    {
        $this->validate();
        try {
            Posts::create([
                'title' => $this->title,
                'description' => $this->description
            ]);
            session()->flash('success','Post Created Successfully!!');
            $this->resetFields();
            $this->addPost = false;
        } catch (\Exception $ex) {
            session()->flash('error','Something goes wrong!!');
        }
    }
 
    /**
     * show existing post data in edit post form
     * @param mixed $id
     * @return void
     */
    public function editPost($id){
        try {
            $post = Posts::findOrFail($id);
            if( !$post) {
                session()->flash('error','Post not found');
            } else {
                $this->title = $post->title;
                $this->description = $post->description;
                $this->postId = $post->id;
                $this->updatePost = true;
                $this->addPost = false;
            }
        } catch (\Exception $ex) {
            session()->flash('error','Something goes wrong!!');
        }
 
    }
 
    /**
     * update the post data
     * @return void
     */
    public function updatePost()
    {
        $this->validate();
    try {
            $post = Posts::find($this->postId);
            $post->title = $this->title;
            $post->description = $this->description;
            $post->save();
            session()->flash('success','Post Updated Successfully!!');
            $this->resetFields();
            $this->updatePost = false;
        } catch (\Exception $ex) {
        session()->flash('error','Something went wrong. Please try again.');
        }
        }
       
    /**
     * Cancel Add/Edit form and redirect to post listing page
     * @return void
     */
    public function cancelPost()
    {
        $this->addPost = false;
        $this->updatePost = false;
        $this->resetFields();
    }
 
    /**
     * delete specific post data from the posts table
     * @param mixed $id
     * @return void
     */
    public function deletePost($postId)
    {
        try{
            Posts::find($postId)->delete();
            session()->flash('success',"Post Deleted Successfully!!");
        }catch(\Exception $e){
            session()->flash('error',"Something goes wrong!!");
        }
    }
}

In the “render” method of the component, we can return the view for our blog by using the “view” helper function. For example, we can return the view “livewire.posts” by adding the line “return view(‘livewire.posts’);” in the render method.

Step 3: Creating the View

Now that we have our Livewire component set up, we can create the view for our blog. In the “resources/views” directory, create a new folder called “livewire”. In the “livewire” folder, create a new file called “post.blade.php”. This will be the main view for our blog.

In the “post.blade.php” file, we can add the HTML and Blade syntax for our blog. We can also use Livewire directives to create dynamic functionality in our view.

resources/views/livewire/post.blade.php

<div>
    <div class="col-md-8 mb-2">
        @if(session()->has('success'))
            <div class="alert alert-success" role="alert">
                {{ session()->get('success') }}
            </div>
        @endif
        @if(session()->has('error'))
            <div class="alert alert-danger" role="alert">
                {{ session()->get('error') }}
            </div>
        @endif
        @if($addPost)
            @include('livewire.create')
        @endif
        @if($updatePost)
            @include('livewire.update')
        @endif
    </div>
    <div class="col-md-8">
        <div class="card">
            <div class="card-body">
                @if(!$addPost)
                <button wire:click="addPost()" class="btn btn-primary btn-sm float-right">Add New Post</button>
                @endif
                <div class="table-responsive">
                    <table class="table">
                        <thead>
                            <tr>
                                <th>Name</th>
                                <th>Description</th>
                                <th>Action</th>
                            </tr>
                        </thead>
                        <tbody>
                            @if (count($posts) > 0)
                                @foreach ($posts as $post)
                                    <tr>
                                        <td>
                                            {{$post->title}}
                                        </td>
                                        <td>
                                            {{$post->description}}
                                        </td>
                                        <td>
                                            <button wire:click="editPost({{$post->id}})" class="btn btn-primary btn-sm">Edit</button>
                                            <button wire:click="$emit('deletePostListner', {{$post->id}})" class="btn btn-danger btn-sm">Delete</button>



                                        </td>
                                    </tr>
                                @endforeach
                            @else
                                <tr>
                                    <td colspan="3" align="center">
                                        No Posts Found.
                                    </td>
                                </tr>
                            @endif
                        </tbody>
                    </table>
                </div>
            </div>
        </div>
    </div>
 
</div>

Step 4: Creating the Model

To create the model for our blog, we will be using Laravel’s built-in command line tool. In the command line, navigate to the project directory and run the command php artisan make:model Post -m. This will create a new model called Post and also create a new migration file for creating the posts table in the database. In this migration file, we can define the columns we want our posts table to have.

App/Models/Post.php

<?php

namespace App\Models;

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


class Post extends Model
{
    use HasFactory;
    protected $fillable = [
        'title', 'description'
    ];
      public $timestamps = true;
}

create_posts_table.php

<?php

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

return new class extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->string('title')->nullable();
            $table->text('description')->nullable();
            $table->timestamps();
        });
    }


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

Next, we will run the command php artisan migrate to create the posts table in the database.

Step 5: Create and Update Blade Files

Now we need to add to more files for creating and updating our posts. As you can see from the posts.php it has the create and update functions. So let’s begin.

resources/views/livewire/create.blade.php

<div class="card">
    <div class="card-body">
        <form>
            <div class="form-group mb-3">
                <label for="title">Title:</label>
                <input type="text" class="form-control @error('title') is-invalid @enderror" id="title" placeholder="Enter Title" wire:model="title">
                @error('title')
                    <span class="text-danger">{{ $message }}</span>
                @enderror
            </div>
            <div class="form-group mb-3">
                <label for="description">Description:</label>
                <textarea class="form-control @error('description') is-invalid @enderror" id="description" wire:model="description" placeholder="Enter Description"></textarea>
                @error('description')
                    <span class="text-danger">{{ $message }}</span>
                @enderror
            </div>
            <div class="d-grid gap-2">
                <button wire:click.prevent="storePost()" class="btn btn-success btn-block">Save</button>
                <button wire:click.prevent="cancelPost()" class="btn btn-secondary btn-block">Cancel</button>
            </div>
        </form>
    </div>
</div>

This code is a form template for updating a post in a Laravel Livewire application. The form has two input fields: one for the post title and one for the post description. The input fields use the “wire:model” attribute to bind the input values to the corresponding variables in the component’s logic. The form also includes two buttons: one for saving the post, and one for cancelling the update. The “storePost()” and “cancelPost()” methods are called when the buttons are clicked. Additionally, the code includes error handling, where it will show an error message if the input is invalid and the error message will be displayed next to the input field.

resources/views/livewire/update.blade.php

<div class="card">
    <div class="card-body">
        <form>
            <div class="form-group mb-3">
                <label for="title">Title:</label>
                <input type="text" class="form-control @error('title') is-invalid @enderror" id="title" placeholder="Enter Title" wire:model="title">
                @error('title')
                    <span class="text-danger">{{ $message }}</span>
                @enderror
            </div>
            <div class="form-group mb-3">
                <label for="description">Description:</label>
                <textarea class="form-control @error('description') is-invalid @enderror" id="description" wire:model="description" placeholder="Enter Description"></textarea>
                @error('description')
                    <span class="text-danger">{{ $message }}</span>
                @enderror
            </div>
            <div class="d-grid gap-2">
                <button wire:click.prevent="updatePost()" class="btn btn-success btn-block">Save</button>
                <button wire:click.prevent="cancelPost()" class="btn btn-secondary btn-block">Cancel</button>
            </div>
        </form>
    </div>
</div>

This is a form for updating a post in a blog that uses Laravel Livewire. The form consists of two input fields, one for the title and one for the description of the post. Both input fields are bound to the component’s properties using the wire:model directive, which allows for two-way data binding between the input fields and the component’s properties. The form also includes two buttons, one for submitting the form and one for cancelling the update.

The form includes error handling using Blade directives, @error and @enderror, which will check if there are any validation errors on the input fields and display a text-danger span with the error message if there are any.

The “Save” button is bound to the component’s “updatePost()” method using the wire:click.prevent directive, which will prevent the default form submission behavior and trigger the “updatePost()” method when clicked. The “Cancel” button is bound to the component’s “cancelPost()” method in the same way, which will cancel the update process.

Step 6: Home Blade

resources/views/home.blade.php

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Livewire Crud</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">  
    @livewireStyles
</head>
<body>
    <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
        <div class="container-fluid">
            <a class="navbar-brand" href="/">Livewire CRUD Blog</a>
        </div>
    </nav>
    <div class="container">
        <div class="row justify-content-center mt-3">
            @livewire('post')
        </div>
    </div>
 
    @livewireScripts
  </body>
</html>

This is the main layout file for the application, it includes the basic HTML structure, links to Bootstrap and Livewire styles, and includes the Livewire component for the post page. It also includes a navigation bar at the top of the page with a title “Livewire CRUD Blog”. It uses the @livewireStyles and @livewireScripts directives to include the necessary CSS and JavaScript files for Livewire components to work.

Step 7: Web File

routes/web.php

Update this file as follows…

Route::get('/', function () {
    return view('home');
});

 

close

Sign up for free tutorials in your inbox.

We don’t spam! Read our privacy policy for more info.

Leave a Comment

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