DEV Community

Cover image for My first Laravel Livewire Volt component
Roberto B.
Roberto B.

Posted on

My first Laravel Livewire Volt component

Laravel Livewire Volt is a Livewire package that allows the developer to create Livewire components with the template and the PHP logic in a blade file.
If you are familiar with creating Vue, React, or Svelte components, you know you can define the templating and logic parts in one component file.
The logic determines the component's behavior and allows the developer to manage user interactions. For example, you can create an interactive component, allowing the end user to execute some logic triggered by an interaction, like clicking a button.

The idea

To explore the Volt capabilities, we will create a new Laravel application, install Livewire, install and configure Livewire Volt and create our first component.

The component we are going to create is a component that allows us to simulate rolling the dice. Clicking a button, a number between 1 and 6 will be generated. The front end will be updated automatically based on the newly drawn value.

Our first Volt component

This is a super simple component, but it allows us to explore how to manage the Volt state, trigger logic (implemented in PHP), and update the frontend part.

Let's create the Laravel Livewire project

So first, create your Laravel application, and add Livewire and Livewire Volt. We will install the beta version because Laravel Livewire 3 and Laravel Livewire Volt 1 still need to be released as stable.

laravel new roll-the-dice-volt
cd roll-the-dice-volt
composer require livewire/livewire:^3.0@beta
composer require livewire/volt:^1.0@beta
Enter fullscreen mode Exit fullscreen mode

Now you installed the needed packages, and you can install the needed file for proper usage of Volt.

php artisan volt:install
Enter fullscreen mode Exit fullscreen mode

The volt:install command will install the ServiceProvider file for the Volt setup.

Creating the Volt component

The ServiceProvider ships the default configuration for loading the Livewire components from the directories resources/views/livewire and resources/views/pages. But we are in good hands because if you want to create a new component, you can use the make:volt artisan command.

If you want to create the rollthedice component, you can launch the following:

php artisan make:volt RollTheDice
Enter fullscreen mode Exit fullscreen mode

the make:volt command lowers the file's name's case and creates the file in the right place: resources/views/livewire/rollthedice.blade.php.

Loading the component on the Home page

Once we have created the rollthedice component, we can include it in your pages. For example, the default page for a newly created Laravel project is the resources/views/welcome.blade.php file. So, in that file, we can include the Livewire component using the livewire tag:

<livewire:rollthedice />
Enter fullscreen mode Exit fullscreen mode

Implementing the component

Now we can focus on the component implementation.
The logic is easy, we want to use two variable states:

  • dice: for storing the current value (generated by the random_int() function every time the end user clicks on the button for rolling the dice;
  • rolls: storing all the drawn values because the end user can roll the dice more than once.

And for demonstration purposes, we want to manage a third variable, a computed variable named total. The computed variable is a variable that is "calculated" every time the function is called. So in this simple example, we want to update the total of the drawn values.

The code of the component is:

<?php

// 001 importing the computed and state functions
use function Livewire\Volt\computed;
use function Livewire\Volt\state;

// 002 setting the 'dice' integer state as 0
state(['dice' => 0]);
// 003 setting the 'rolls' array state as an empty array
state(['rolls' => []]);
// 004 defining the `roll` function for generating a random number
$roll = function () {
    $this->dice = random_int(1, 6);
    $this->rolls[] = $this->dice;
};
// 005 defining the `restart` function for resetting the state values
$restart = function () {
    $this->dice = 0;
    $this->rolls = [];
};
// 006 defining the computed `total` function for calculating the sum of values
$total =
    computed(function () {
        return array_sum($this->rolls);
    });
?>
<div class="max-w-7xl  text-center">
    <div class="stats shadow">
        <div class="stat">
            <div class="stat-title">Number</div>
            <div class="stat-value">{{ $dice }}</div>
            <div class="stat-desc">Drawed number</div>
        </div>
        <div class="stat">
            <div class="stat-title">Number of rolls</div>
            <div class="stat-value">{{ sizeof($rolls) }}</div>
            <div class="stat-desc">Number of times the dice were rolled</div>
        </div>
        <div class="stat">
            <div class="stat-title">Total</div>
            <div class="stat-value">{{ $this->total }}</div>
            <div class="stat-desc">Sum of all numbers drawn</div>
        </div>
    </div>
    <div class="p-5 text-center">
        <button class="btn btn-primary mx-5" wire:click="roll">Let's roll the dice</button>
        <button class="btn btn-secondary mx-5" wire:click="restart">Restart</button>
    </div>
    <div class="p-1 text-center w-128 ">
        All the rolls :
        @foreach ($rolls as $roll)
            {{ $roll }} /
        @endforeach
    </div>
</div>
Enter fullscreen mode Exit fullscreen mode

The file component (a blade file) is made of two parts.

The first part is the logic, where we declare the states, defines the computed function, and implement a couple of anonymous function that we will trigger via the end-user action by clicking the button.

The second part of the blade file is the template with the HTML needed for rendering the component.

In the code, I added some placeholder comments. Let's walk through the relevant part:

  • 001: importing the computed and state functions;
  • 002: setting the dice state for storing the current values;
  • 003: setting the rolls state for storing the list of the values;
  • 004: defining the roll function for generating a random number and adding the value in the rolls array;
  • 005: defining the restart function for resetting the dice state value and re-initializing the array of rolls
  • 006: defining the computed total function for calculating the sum of values

A note about the computed function

A computed function is a function that is executed once, and then the value is cached. In this example, the computed function probably has no sense because, under the hood, we are calling the array_sum() function (a fast and in-memory function with no delay). But what if the logic involves a database query or an API call (some operations with potential latency)?
You can evaluate using the computed functions that cache the results in this case. But please remember that Livewire only caches the result for the duration of a single component request. More info about computed functions in Livewire 3: https://livewire.laravel.com/docs/computed-properties.

So, again, in this example, we are using the computed function to demonstrate how we can declare a computed function and how to call the computed function.

A note about "how to call" the computed function: to access the value of the computed function, you need to use the $this-> syntax to access the $this object.

My thoughts about Livewire Volt component

This example is useful to understand how the Livewire Volt components work and how to implement a new one.
But, I will be honest with you, for this specific use case, where the logic could be executed only in the front end, it is better to choose a simple Javascript code or use Svelte, Vue, or React.

So, when using the Volt components approach, could it be useful?
Of course, when the logic you need to implement requires some server-side execution because (for example) you need to access a database, or you need to access APIs with some secret tokens, etc.
This is because the function you declare is executed on the server side. If you inspect the traffic on the network, you will see a Livewire HTTP call every time the roll() function is called or the reset() function is called.
So with this approach, you can introduce latency, so you have no real benefit if the logic is pure frontend logic.
It is different when dealing with server-side executable business logic.
And you, what do you think? Please feel free to reply in the comments or give any feedback. I'm curious about your opinion.

Top comments (0)