Handling forms in Laravel Livewire through a component

- Andrés Cruz

En español
Handling forms in Laravel Livewire through a component

Laravel Livewire is a skeleton for Laravel that allows you to create interactive user interfaces without writing JavaScript. One of its main features is its ability to handle forms and form submissions, since we have multiple methods and attributes that we can use directly to communicate the frontend with the backend. With Livewire, it's much easier to create complex forms with validation and error handling, as well as AJAX form submissions without any extra effort. In this way, Livewire simplifies the process of managing forms and their submissions in Laravel applications.

To create a basic form in Livewire, you must first create a Livewire component and then define the public properties that will hold the form data. So, you need to create a method to handle the form submission and validate the data using Laravel's validation functions. Finally, you must add the form's HTML markup with the wire:model attributes to bind to the public properties.

In this article, we are going to create a component in Livewire, which is the structure that we have to use in order to take advantage of the main benefits of Laravel Livewire.

Remember that in order to continue, you must know how to create a project in Laravel Livewire.

We create the component with:

php artisan make:livewire Dashboard/Category/Save

We create the route with:

  Route::group(['prefix' => 'category'],function () {
        Route::get('/create', App\Http\Livewire\Dashboard\Category\Save::class)->name("d-category-create");  // crear
        Route::get('/edit/{id}', App\Http\Livewire\Dashboard\Category\Save::class)->name("d-category-edit");// edit
    });

And the model looks like the following:

class Category extends Model
{
    use HasFactory;
    protected $fillable=['title','slug','image','text'];
    public function posts()
    {
        return $this->hasMany(Post::class);
    }
    public function getImageUrl()
    {
        return URL::asset("images/".$this->image);
    }
}

In the component view, we define our form for managing the categories:

<form wire:submit.prevent="submit">
<x-jet-label for="">Título</x-jet-label>
<x-jet-input-error for="title" />
<x-jet-input type="text" wire:model="title" />
<x-jet-label for="">Texto</x-jet-label>
<x-jet-input-error for="text" />
<x-jet-input type="text" wire:model="text" />
<x-jet-button type="submit">Enviar</x-jet-button>
</form>

And in the component class:

namespace App\Http\Livewire\Dashboard\Category;
use App\Models\Category;
use Illuminate\Support\Facades\Log;
use Livewire\Component;
use Livewire\WithFileUploads;
class Save extends Component
{
    use WithFileUploads;
    public $title;
    public $text;
    public $image;
    public $category;
    protected $rules = [
        'title' => "required|min:2|max:255",
        'text' => "nullable",
        'image' => "nullable|image|max:1024",
    ];
    public function mount($id = null)
    {
        if ($id != null) {
            $this->category = Category::findOrFail($id);
            $this->title = $this->category->title;
            $this->text = $this->category->text;
        }
    }
    public function render()
    {
        //Log::info("render");
        return view('livewire.dashboard.category.save');
    }
    public function submit()
    {
        // validate
        $this->validate();
        // save
        if ($this->category){
            $this->category->update([
                'title' => $this->title,
                'text' => $this->text,
            ]);
            $this->emit("updated");
        }else{
           $this->category = Category::create(
            [
                'title' => $this->title,
                'slug' => str($this->title)->slug(),
                'text' => $this->text,
                ]
            );
            $this->emit("created");
        }
        // upload
        if($this->image){
            $imageName = $this->category->slug . '.' . $this->image->getClientOriginalExtension();
            $this->image->storeAs('images', $imageName,'public_upload');
    
            $this->category->update([
                'image'=> $imageName
            ]);
        }
    }
}

Notice that in the submit function we handle both processes, that of creating and editing according to the status of a category that exists only if we are in the editing phase and that we initialize in the component mount phase.

These are the phases of any CRUD process and at Livewire they are very straightforward processes as we have already seen.

Andrés Cruz

Develop with Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter

Andrés Cruz In Udemy

I agree to receive announcements of interest about this Blog.