Livewire – 14 Tips & Tricks to Achieve Dynamic Behavior in Web App

Livewire – 14 Tips & Tricks to Achieve Dynamic Behavior in Web App

Proven practical tips and tricks of Livewire

Want to develop a modern web app?

Vue and react are JavaScript-based toolkit systems to build dynamic user interfaces. However, the complexity both systems add to a full-stack developer's workflow is insane.

So, it doesn’t have to be this way.

It’s time to say a big hello to Laravel Livewire.

Built around the Laravel framework, Laravel Livewire is a full-stack framework for creating interactive web applications without any custom JavaScript.

According to trends.builtwith.com, more than 38,805 live websites use Laravel Livewire, and over 12,448 sites have used Laravel Livewire historically.

Let’s Understand a Little More About Livewire before Getting bogged down with Tips & Tricks

Livewire is a framework allowing Laravel developers to build reactive and dynamic interfaces using Blade and a fraction of JavaScript. In the past, to build an app, Laravel developers have to:

  • write Blade templates and render an app on the server-side,
  • write backend as APIs that accept and respond with JSON and have to use front-end frameworks like Vue, React, or Angular to consume the APIs and implement the UI.

But now, using Livewire, Laravel developers can easily implement the functionalities like form validation, pagination, notifications, and file upload preview without the page reload. However, Livewire isn’t limited to four functionalities only. Laravel developers can implement it in many ways.

So, let’s dive deep into Livewire to find some extra practical tips that can be applied in real-world applications.

Components in non-default Folder

One may have a Livewire component in a different folder than the default app/Http/Livewire to use some external package with Livewire components. Then, one must bind its name to the actual location. Usually, it is done in app/Providers/AppServiceProvider.php or any service provider through method boot():

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        Livewire::component('shopping-cart', \Modules\Shop\Http\Livewire\Cart::class);
    }
}

Rename or Move Components with Ease

Do not worry if you have created a typo while generating the component with make:livewire, as Livewire provides you the command to rename two files manually.

Suppose you have written php artisan make:livewire Servie, but you want "Service "in its place and decided to place it into a subfolder. You can follow through below given command:

php artisan livewire:move Prduct Products/Show

The outcome will be:

COMPONENT MOVED
CLASS: app/Http/Livewire/servie.php
    => app/Http/Livewire/service/Show.php 

VIEW:  resources/views/livewire/servie.blade.php
    => resources/views/livewire/service/show.blade.php

Change Default Component Templates

Using the default templates, "stubs", you can generate Livewire components. These components are hidden away in the "vendor" folder of the Livewire package; however, you can publish them and edit them according to the requirements. To change default components templates, run the below command:

php artisan livewire:stubs

Now, you will get a new folder ‘/stub’ with a few files. Here is the example of a stubs/livewire.stub:

<?php

namespace [namespace];

use Livewire\Component;

class [class] extends Component
{
    public function render()
    {
        return view('[view]');
    }
}

Moreover, if you want to generate the components without the render() method, you must remove it from the stub file. When you runphp artisan make:livewire Component,it will take the template from your updated public stub.

No render() needed

A common render() method looks like:

// app/Http/Livewire/PostsShow.php
class PostsShow extends Component
{
    public function render()
    {
        return view('livewire.posts-show');
    }
}

You may also delete that render() method from the component but extract the default view if your render() method is a one-line. Moreover, it will also work by loading the default render() from the vendor's method.

class PostsShow extends Component
{
    // This empty component will still work and load the Blade file
}

Components in Subfolders

There are two ways to generate a component in a subfolder like app/Http/Livewire/Folder/Component.php.

php artisan make:livewire Folder/Element

or

php artisan make:livewire folder.element

The first way is with the first letter uppercase, whereas the second way is lowercase. For both the cases, two different files will be generated, i.e.

app/Http/Livewire/Folder/ Element.php resources/views/livewire/folder/element.blade.php

Note: If components don't exist, the subfolders will be created automatically.

Don't Create a Method to Set Value Only

When you click event to set some value of some property, you have to do something like:

<button wire:click="showText">Show</button>

And then

class Show extends Component
{
    public $showText = false;

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

However, you can easily assign a new value to the Livewire property from the Blade file directly without partaking in a different method in the Livewire component.

Check out the code below:

<button wire:click="$set('showText', true)">Show</button>

Now, call the $set and provide two parameters, i.e., the new value and property name.

Easily Set True/False Value

If your property is a boolean variable with true/false values, then you must have a show/hide button by doing this:

<button wire:click="$toggle('showText')">Show/Hide</button>

It is advisable to use JavaScript instead of Livewire for a simple toggle, as it adds the request to the server. Checkout below script:

<div x-data="{ open: false }">
    <button @click="open = true">Expand</button>

    <span x-show="open">
      Content...
    </span>
</div>

Customize Validation Attributes

Like the Laravel validation engine, Livewire validation works, but with some differences. If you want to customize the name of the attributes in Laravel, you have to define the attributes() method in a Form Request class, whereas in Livewire, there is a different approach. One should have to define a property called $validationAttributes in the component and assign the array of key-value.

Check out the below code:

class ContactForm extends Component
{
    protected $validationAttributes = [
        'email' => 'email address'
    ];

    // ...

Here, the common error messages, like "Field [ABC] is required", where ABC is replaced with the field name.

Loading Indicators

It is seen that the described thing in the official documentation is rarely used. It is worth displaying some loading message when some action takes a while on the screen, i.e., a spinning gif or just a text of "Your data is loading..." It is easy to customize and implement in Livewire.

The common example of processing data is when the server request is made, and it displays 'Your Payment is processing' until the server request is completed and displayed with the result.

<div>
    <button wire:click="checkout">Checkout</button>

    <div wire:loading>
        Processing Payment...
    </div>
</div>

Practically, it only displays such loading indicators for a while. There is no point in re-rending the DOM in every possible case. What if we do it only if the request takes over 500ms?

<div wire:loading.delay.longer>...</div>

Here are the possibilities of playing around with CSS classes to load states and attach them to specific actions.

Minimize Server Requests with These Three Ways

There are too many requests to the server in Livewire. It is considered as of the main criticisms of Livewire. Each keystroke would hypothetically call the server if there is a wire:model on the input field to re-render the component. In addition, it would be more convenient to have some real-time effects, like "live search". However, the server requests may be quite expensive performance-wise. It is possible to customize this behavior of wire:model.

  • wire:model.debounce: Livewire waits for 150ms, by default, after the keystroke on the input, before performing the request to the server. However, you can override it: <input type="text" wire:model.debounce.1000ms="propertyName">

  • wire:model.lazy: Livewire listens for all events on the input by default and then performs the server requests. With a lazy directive, you state Livewire to listen only to the change event. That means users may keep typing and changing the value, and the changes will be effective when the user clicks away from that field.

  • wire:model.defer: It will not fire the server requests when the input changes. It will save the new value internally and pass it to the next network request from the other button clicks or other input fields.

Offline Indicator

Another less-known feature lets users know that their internet connection is lost. It works when an application works with real-time data or multiple updates on the screen. Or, you may have some portion of web pages blur and show the "offline" text.

<div wire:offline>
    You are offline now.
</div>

You can also blur some elements, by assigning CSS classes like:

<div wire:offline.class="bg-blue-300"></div>

Delete Confirm Modal

Below given code wouldn't work correctly in Livewire when you have a Delete button, and you want to call the confirm JavaScript modal before taking action.


<button wire:click="delete($post->id)"
        onclick="return confirm('Are you sure?')">Delete</button>

Here’re some possible solutions. Probably, the most elegant is to stop the Livewire event before it is even happening:

<button onclick="confirm('Are you sure?') || event.stopImmediatePropagation()"
        wire:click="delete($post->id)">Delete</button>

When the confirmation result is false, that event.stopImmediatePropagation() will stop the Livewire method from being called.

Pagination with Bootstrap Framework

Livewire uses pagination styling from the Tailwind framework, just like Laravel. It is simple to override by providing the different values to the property like:

class ShowPosts extends Component
{
    use WithPagination;

    protected $paginationTheme = 'bootstrap';

Note: Check out available pagination designs directly in Livewire Github repository.

No Mount: Automatic Route-Model Binding

Pass an object to the Livewire component with the mount() method:

class ShowPost extends Component
{
    public $post;

    public function mount(Post $post)
    {
        $this->post = $post;
    }
}

Then you have @livewire('show-post', $post) somewhere in Blade. If you provide a type-hint to the Livewire property, route-model binding would happen automatically.

class ShowPost extends Component
{
    public Post $post;
}

That's it, you don’t have to implement the mount() method at all.

Get Started with Laravel Livewire

From Turbolinks integration to Alpine JS integration, we have seen the magic of abridging the complex jQuery ajax code using PHP with Laravel LiveWire. So, what are you waiting for? Get started by implementing above mentioned tips and tricks for your Laravel development. And, if you find any difficulties in implementing, connect with our Laravel Development team for a quick solution.