Laravel Livewire for Beginners – Full 2021 Guide | RJS

Laravel Livewire for Beginners – Full 2021 Guide

Ralph J. Smit Laravel & PHP-developer.

If you've been coding with Laravel for some time, you must have heard about the 'magical' Laravel Livewire package. Livewire is a truly awesome (and almost magic) way to create interactive interfaces and communicate 'realtime' with your Laravel backend. And it does this all in a very simple way. In this article I'll show you the basics of Laravel Livewire, so that you will be up-and-running with Livewire in no-time🚀

The combination of simplicity and power is what makes Laravel Livewire so awesome and why it is used by so many developers. It is especially a good alternative to the Laravel + Inertia + Vue combination, in particular if you're still used to the 'Vue-magic', but feel that Vue is too much of a hassle to set up.

The basics of Livewire

The first thing you should know is that Livewire works with so-called components. That means that you can have a search component, an edit component, you name it. Each Livewire component consists of (in most cases) two files:

  • The component class file

  • The Blade file with the markup (the HTML)

Additionally, you could also have a test for each component, but that's something you should care about later (but don't forget it!😄).

Installing Livewire

First, you need to install Laravel Livewire. To do so, run the following composer command:

composer require livewire/livewire

Next, you need to load a Livewire JavaScript file and a Livewire CSS file. Without loading those files on a page, you cannot use Livewire. Luckily, Livewire makes this really easy for us. All you need to do is adding the below two Blade directives in your Blade files and make sure that these directives are loaded on every page.

The best place to put them is normally in your layouts/app.blade.php file:

<html>
<head>
...
@livewireStyles
</head>
<body>
...
@livewireScripts
</body>
</html>

Creating Livewire components

Now it's time to create our first Livewire component! The best way to create a Livewire component is to run the following artisan command, similar to the regular Laravel artisan commands:

php artisan make:livewire ComponentName

This will create two files, the file with the Livewire logic and the Blade layout:

  • App\Http\Livewire\ComponentName.php

  • resources/views/livewire/component-name.blade.php

You can also create a Livewire component in a namespace:

php artisan make:livewire Dashboard/ComponentName

The above command creates the following two files:

<?php
 
namespace App\Http\Livewire;
 
use Livewire\Component;
 
class ComponentName extends Component
{
public function render()
{
return view('livewire.component-name');
}
}
<div>
{{-- In work, do what you enjoy. --}}
</div>

With just these two files you can create great interactive Livewire components!

Creating a Livewire search component

So, what's so special about Livewire? The special 'magic' thing about Livewire is that it allows (almost) realtime communication between your server (the backend) and the frontend. This means that you could have a variable, change it in your PHP and the frontend automatically updates with the new values.

Imagine that you have a page in your Laravel app with tabs. You could have a variable that holds the name of the current tab. In your frontend Blade files, you could do an @if() condition to show the correct markup. Changing the variable for example on click, the markup would automatically change without reloading the page!🤯

The Livewire website has a great example on their homepage that shows the power of Livewire, so let's start with that.

use Livewire\Component;
 
class SearchUsers extends Component
{
public $search = '';
 
public function render()
{
return view('livewire.search-users', [
'users' => User::where('username', $this->search)->get(),
]);
}
}
<div>
<input wire:model="search" type="text" placeholder="Search users..."/>
 
<ul>
@foreach($users as $user)
<li>{{ $user->username }}</li>
@endforeach
</ul>
</div>

So, what do we see here? We see that we have a variable in our Livewire component, called **$search**. Every variable (or property or attribute) that you declare as public on the Livewire class, is available to the frontend and it updates realtime.

The frontend has an <input> element where people enter their search query. The value of this input element is 'connected' to the value of the public $search property. And the $users variable that is passed to the frontend, depends on the public $search. So if the value of public $search changes, the value of $users changes and the frontend also updates – without a page reload. Magic, right?

Make sure your template file has one <div> root element

A thing that's good to know is that your Blade template file may only contain a single <div> als root element. This means that all your own code is always inside a single <div>. I'm saying it here, before you find yourself debugging this issue.

PS: you are not restricted to a <div> element, but a div is the most common one. As long as it's only one root element.

How to display a Livewire component

Now that you've got an idea of how a Livewire component looks like, you might be wondering how to display it on a page. There are multiple ways to display a component, so you can choose one of the following ways to include a Livewire component in a Blade file:

<livewire:search-users />
 
@livewire('search-users')
 
@livewire(App\Http\Livewire\SearchUsers::class)

You can also add data to each Livewire component:

@livewire('search-users', [ 'company' => $company ])
// Add the following public property to your SearchUsers component. Livewire will map the $company automatically to the correct property.
public Company $company;
 
// If you want more control over how the properties are stored, you can also accept them in the mount() method:
public Company $myCompany;
 
public function mount(Company $company) {
$this->myCompany = $company;
}

You can also use Livewire as a full-page component. That means that this would work:

use App\Http\Livewire\SearchUsers;
 
Route::get('/{organization}/users/search', SearchUsers::class);
public function render()
{
return view('livewire.search-users', [
'users' => User::where('username', $this->search)->get(),
])->extends('layouts.app');
}

Checkout the Livewire docs for more information if you're interested in using fullpage components.

Using Actions

Another very handy thing is the use of Livewire actions. Livewire actions mean you can define a public function on your component and call this action from the frontend. For example, if a user clicks on a button.

This example comes from the docs and I think that it's a great example that shows the power of Livewire really well:

class ShowPost extends Component
{
public Post $post;
 
public function like(): void
{
$this->post->addLikeBy(auth()->user());
}
}
<div>
<button wire:click="like">Like Post</button>
</div>

As a summary, Livewire will now call the like() function every time the users click the <button>. You can add a wire:click="" directive to every element you want, so it is not limited to buttons and <a href="">s.

Using forms with Laravel Livewire

Next, I would like to talk about forms in Livewire. The way Livewire handles forms might classify as one of the most powerful Livewire features. It wouldn't surprise me if it is one of the most commonly used features.

Let's see how it works.

First, we have the Blade file. Just like in 'regular' non-Livewire HTML, each form is wrapped in a <form> tag. The big difference is that a Livewire form doesn't have the action="", type="" and method="" tags.

So how do we tell Livewire where to send the information to?

We can do so with the wire:submit.prevent attribute. Adding this attribute to the <form> looks like this: <form wire:submit.prevent="save"> . It tells Livewire: 'when the form is submitted, prevent the normal submit action and call the save() function instead.

Let's see this in action. We start by modifying our Blade file so that it contains a very simple form, asking for just an e-mailaddress.

<div>
<form wire:submit.prevent="save">
<input type="email" wire:model="email" placeholder="Email">
 
<button type="submit">Submit form</button>
</form>
</div>

Next, let's add the function save() to the Livewire component:

public function save(): void
{
$this->validate();
 
$user = User::create([
'email' => $this->email,
]);
 
dump('User created successfully!');
}

Let's also add a public property called $email and make sure to set a default value like an empty string, ''. If the field is optional, you can also make the variable type nullable by adding a ? before the type and assigning a default value of null.

public string $email = '';
public ?string $email = null; // Optional field

This property will always contain the value of the input field, because we bind these values together with the wire:model="email" attribute on the input.

You see that we're using the $this->validate() method. This should always be the first method in your save() function, because it will run all the validation rules. If the validation fails, it stops the flow of the code.

So how do we define those rules?

To do so, add a protected $rules property to the Livewire component. (See the power of favouring convention over configuration?)

protected $rules [
'email' => 'required|email'
];

Now, we are almost ready to start using our first Livewire component. We only need a place to display potential error messages.

You can use the @error directive for that. Now our Blade file should look like this:

<div>
<form wire:submit.prevent="save">
<input type="email" wire:model="email" placeholder="Email">
@error('email') <span class="error">{{ $message }}</span>@enderror
 
<button type="submit">Submit form</button>
</form>
</div>

If you want to customize the error messages or the attribute names, checkout the documentation.

Realtime form validation & Livewire lifecycle hooks

Another cool feature I want to show you, is the realtime validation feature. How is that possible?

Livewire allows you to add specific function to the component, like updatedVARIABLENAME(), updatingVARIABLENAME(). Those functions are called lifecycle hooks. You can add them for each variable, and each time that variable is updated, this function will run.

So if we want to validate the $email input every it changes – realtime as the user is typing – we can use a lifecycle hook for that:

public function updatedEmail($value): void
{
$this->validateOnly('email');
}

You can also use a more generic lifecycle hook, which runs on every property update. This is in particular handy if you have long forms and you don't want ten functions all doing the same validation over and over.

public function updated($propertyName): void
{
$this->validateOnly($propertyName);
}

Next steps

As you've seen, Livewire allows PHP-developers to implement pretty amazing interactivity in their Laravel-apps, without developers needing to write a single line of JavaScript.

For developers like me, who have much more feeling with PHP then with JavaScript, Livewire saves so much time.

Now that you know the basics of Livewire, I'd recommend to start using it as much as possible, in order to experience the full power of Livewire. There's so much more I didn't tell here, so start using it, take a dive in the documentation later and enjoy!⚡️

Published by Ralph J. Smit on in Laravel. Last updated on 11 March 2022.


Like what you read?

Get notified when I publish something new, and unsubscribe at any time.