Laravel - Livewire

Livewire v3 Features


The Livewire core has been totally overhauled, and I couldn't be more excited. The new core leans heavily on Alpine, tapping into its Morph, History, and other plugins to take Livewire's capabilities to the next level. This means we can expect improved diffing, quicker feature implementation, and less redundancy between Livewire and Alpine.

What's more, restructuring the codebase and relying on Alpine more has enabled the Livewire team to add several awesome new features that I can't wait to sink my teeth into. As a developer who loves to code, these kinds of updates always get me pumped, and I'm eager to see what Livewire can do with this fresh new foundation.

With Livewire v3, gone are the days of manually adding @livewireStyles, @livewireScripts, and Alpine to your layout after composer installing Livewire v2. Say goodbye to those tedious tasks!

Now, with Livewire v3, it's as simple as installing Livewire, and voila! Everything you need is automatically injected, including the beloved Alpine. As a developer who loves to code, I can't tell you how stoked I am about this upgrade. Livewire v3 is a true timesaver and a testament to the power of thoughtful, streamlined development.

<!DOCTYPE html>
<html lang="en">
<head>
-    <script src="//unpkg.com/alpinejs" defer></script> 
-    @livewireStyles
-    @livewireScripts
</head>
<body>
    ...
</body>
</html>

The upcoming Livewire v3 release is set to include hot reloading, without the need for a pesky build step. That's right - simply save a file in your editor and watch the magic happen in your browser, all without compromising your components' state.

While Alpine has long had transitions, Livewire v3 will be taking it up a notch with the introduction of a wrapper around x-transition called wire:transition. Simply add wire:transition to any element that will be shown or hidden using Livewire, and voila! Enjoy those beautiful, smooth transitions you've been dreaming of.

The best part? Wire:transition utilizes x-transition under the hood, so you can expect full support for modifiers like .opacity and .duration.

One of the standout features? The ability to write JavaScript functions directly in your backend Livewire components.

Here's how it works: Simply add a function to your component, insert a /** @js */ comment above the function, and use PHP's HEREDOC syntax to return some JavaScript code. From there, you can call it from your frontend and watch as the JavaScript code is executed without sending any requests to your backend.

As a developer who loves to optimize workflows and streamline processes, this is a total game-changer. With Livewire v3, we're breaking down barriers and unlocking new potential for dynamic, efficient web development. Get ready to take your Livewire projects to the next level with this powerful new feature!

<?php
 
namespace App\Http\Livewire;
 
class Todos extends \Livewire\Component
{
    /** @prop */
    public $todos;
 
    /** @js  */
    public function clear()
    {
        return <<<'JS'
            this.todo = '';
        JS;
    }
}
<div>
    <input wire:model="todo" />
 
    <button wire:click="clear">Clear</button> 
</div>

With Livewire v3, you can mark properties as "locked" by adding a simple /** @locked */ comment above the property on your component. From there, if anyone attempts to update that property from the frontend, Livewire will throw an exception and prevent the update from going through.

<?php
 
namespace App\Http\Livewire;
 
class Todos extends \Livewire\Component
{
    /** @locked  */
    public $todos = [];
}

Livewire was initially designed to write components such as search that required a dynamic and interactive interface, and therefore, sending automatic updates to the server every time an input was modified was logical. However, Livewire has now become a tool for creating various types of applications. During its evolution, it became evident that the "deferred" behavior was suitable for the majority of forms, and hence, it will be the default in version 3. This change will optimize performance by reducing unnecessary server requests.

If you require the "live" functionality for a specific input, you can use wire:model.live to enable it.

It is essential to note that this is one of the few breaking changes from version 2 to version 3.

When using Livewire v2, if you had several components that used wire:poll or dispatched and listened for events, each of these components would send separate requests to the server for every poll or event. However, Livewire v3 incorporates intelligent batching to consolidate these requests into a single one, whenever possible. This includes wire:polls, events, listeners, and method calls. This enhancement reduces the number of requests sent to the server, which leads to better performance.

In Livewire v2, when utilizing nested components, modifications made to a property in the parent component do not automatically synchronize with the data in the child component. While workarounds involving events and listeners are possible, they are not ideal. Fortunately, Livewire v3 has a better solution. When passing data to a child component, simply add a /** @prop */ comment above the related property in the child component. Then, when you modify the data in the parent component, it will automatically update in the child component, resolving any synchronization issues.

<?php
 
namespace App\Http\Livewire;
 
class TodosCount extends \Livewire\Component
{
    /** @prop */
    public $todos;
 
    public function render()
    {
        return <<<'HTML'
            <div>
                Todos: {{ count($todos) }}
            </div>
        HTML;
    }
}

One of the challenges in Livewire v2 is modeling a property from a parent component to a child component. For instance, suppose you wanted to use a <livewire:todo-input /> component. In that case, it was not simple to pass a value to the child component and have it automatically update the parent component whenever it was modified in the child component. Fortunately, Livewire v3 offers an efficient solution. When using the input component, add the wire:model directive. Then, within the input component, add a /** @modelable */ comment above the property that stores the component's value, and Livewire will manage the rest of the process.

<?php
 
namespace App\Http\Livewire;
 
class Todos extends \Livewire\Component
{
    public $todo = '';
 
    public $todos = [];
 
    public function add() ...
 
    public function render()
    {
        return <<<'HTML'
            <div>
                <livewire:todo-input wire:model="todo" /> 
                <ul>
                    @foreach ($todo as $todos)
                        <li>{{ $todo }}</li>
                    @endforeach
                </ul>
            </div>
        HTML;
    }
}
<?php
 
namespace App\Http\Livewire;
 
class TodoInput extends \Livewire\Component
{
    /** @modelable  */
    public $value = '';
 
    public function render()
    {
        return <<<'HTML'
            <div>
                <input wire:model="value">
            </div>
        HTML;
    }
}

Livewire v3 introduces a novel approach to reach the data and methods of a parent component. The $parent property is now available, enabling users to invoke methods on the parent.

<?php
 
namespace App\Http\Livewire;
 
class TodoInput extends \Livewire\Component
{
    /** @modelable  */
    public $value = '';
 
    public function render()
    {
        return <<<'HTML'
            <div>
                <input
                    wire:model="value"
                    wire:keydown.enter="$parent.add()"
                >
            </div>
        HTML;
    }
}

Another feature coming with Livewire v3 is the @teleport Blade directive. This directive permits users to "teleport" a specific section of markup and display it in another area of the Document Object Model (DOM). In certain cases, this functionality can help circumvent z-index problems related to slideouts and modals.

<div>
    <button wire:click="showModal">Show modal</button>
 
    @teleport('#footer')
        <x-modal wire:model="showModal">
            <!-- ... -->
        </x-modal>
    @endteleport
</div>

Livewire v3 will introduce the concept of "lazy" components. If a component involves a computationally expensive query or is rendered within a slideout that isn't always visible, it may be better to postpone its loading until it is required. To accomplish this in Livewire v3, add a lazy attribute to the component's rendering code, and it won't load initially. Instead, when the component enters the viewport, Livewire will trigger a request to load and render it. Additionally, by implementing the placeholder method on your component, you can include placeholder content.

<div>
    <button wire:click="showModal">Show modal</button>
 
    @teleport('#footer')
        <x-modal wire:model="showModal">
            <livewire:example-component lazy /> 
        </x-modal>
    @endteleport
</div>
<?php
 
namespace App\Http\Livewire;
 
class ExampleComponent extends \Livewire\Component
{
    public static function placeholder()
    {
        return <<<'HTML'
            <x-spinner />
        >>>
    }
 
    public function render() /** [tl! collapse:7] */
    {
        return <<<'HTML'
            <div>
                Todos: {{ count($todos) }}
            </div>
        HTML;
    }
}

Livewire v3 enables users to attach wire:navigate to any anchor tag. Once clicked, Livewire will swiftly retrieve the page in the background and swap out the Document Object Model (DOM), enhancing the application's Single Page Application (SPA)-like experience. To further enhance performance, add the .prefetch modifier, which will fetch the link's contents as soon as it is hovered over.

<a href="/example" wire:navigate.prefetch>Example Page</a>

Livewire v3 introduces another Blade directive, @persist. Using @persist with wire:navigate, you can make parts of your application "persist" throughout page changes. For instance, this feature is ideal for a podcast player that continues to play while you navigate through the app.

<!DOCTYPE html>
<html lang="en">
<body>
    <x-podcast-header />
 
    <x-podcast-body>
        {{ $slot }}
    </x-podcast-body>
 
    @persist('player')
        <x-podcast-player />
    @endpersist
</body>
</html>

I am absolutely thrilled about all the exciting new features coming to Livewire v3! If you're anything like me then I highly recommend supporting the development of v3 and taking advantage of the help available through the official Support Program. Trust me, you won't regret it!

Read more Articles