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.
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
Now you installed the needed packages, and you can install the needed file for proper usage of Volt.
php artisan volt:install
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
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 />
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 therandom_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>
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
andstate
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 therolls
array; - 005: defining the
restart
function for resetting thedice
state value and re-initializing the array ofrolls
- 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 (2)
mm I can't wrap my head around this yet, is that different of vanilla livewire components?
You are probably more familiar with the "vanilla Livewire Components" structure and syntax. This is fine.
You can use the functionalities :
I think I can write a post similar to this one for using Livewire components instead of Volt.
Under the hood, in the end, Volt components are "compiled" as Livewire class components.