Get your next remote job on LaraJobs.
Laravel Livewire Packages

Laravel Volt: simplify how you write Livewire components

Benjamin Crozat
Modified on Aug 12, 2023 3 comments Edit on GitHub
Laravel Volt: simplify how you write Livewire components

Introduction

Laravel Volt was introduced in Laracon US 2023. The package brings single-file components à la Vue.js to Livewire v3.

This is a step-by-step tutorial to help you quickly get started with this elegant addition to the Laravel ecosystem.

Please understand that to be able to follow this tutorial, being familiar with class-based Livewire v3 components is necessary.

What is Laravel Volt?

Laravel Volt is a way to write single-file Livewire v3 components by leveraging a new declarative API.

If you are familiar with JavaScript frameworks like Vue.js, you know what I’m talking about.

For the others, don’t worry, you’ll get it once you see it!

How to install Laravel Volt

First, install Laravel Volt using the following command:

composer require livewire/volt

Note that Volt is under the livewire namespace, not laravel.

Then, install the necessary boilerplate to make Laravel Volt work:

php artisan volt:install

This will create VoltServiceProvider.php in app/Providers and register it in your config/app.php file.

How to create a basic newsletter component

To create a component, use the make:volt command:

php artisan make:volt Newsletter 

This will spawn a new file in ./resources/views/livewire/newsletter.blade.php.

Before we continue, did you know that you can also create tests simultaneously? Just pass the --test option. You can even ensure it’s a Pest test by passing --pest instead of --test.

php artisan make:volt Newsletter --test --pest

A test will be created in tests/Feature/Livewire/NewsletterTest.php. But we’ll get back to it shortly!

Now, let’s take a look at our Volt component. Don’t worry; I will detail every line of code.

<?php

use function Livewire\Volt\{rules,state};

state([
    'email' => '',
    'done' => false,
]);

rules([
    'email' => 'required|email',
]);

$submit = function () {
    $this->validate();

    // Subscribe the user.

    $this->done = true;
};

?>

<div>
    @if ($done)
        <p>Thank you for subscribing!</p>
    @else
        <form wire:submit="submit">
            <input type="email" wire:model="email" required />

            <button>
                Subscribe
            </button>
        </form>

        @error('email')
            <p>{{ $message }}</p>
        @enderror
    @endif
</div>

This Volt component aims to subscribe people to our newsletter without sending them to another page. We want the process to feel fast and modern.

  1. We create the form in a classic Laravel-fashion.
  2. We display validation errors.
  3. We intercept the submit action: Instead of using method="POST" action="/some-uri", we bind the submit action to a Livewire function we will define.
  4. We bind the value of our input field to an email state property we will define.
  5. We conditionally display a confirmation message thanks to another state property we will define.
  6. We define our state properties: this is done in a PHP code block at the top of the file. The state properties are email and done.
  7. We validate the email property. Our component must be secure and not store junk data in the database.
  8. We define a submit function that will be called when the form is submitted. Inside, we validate the user’s input based on the previously defined rules, subscribe the user, and set the done state property to true, which will trigger the confirmation message.

Make sure everything works in your browser, and let’s see in the next section how to test that this Volt component behaves as expected.

Keep using class-based components in a single file

If you have a big Laravel project that you want to slowly transition to Volt, you have the possibility of using your existing class-based Livewire v3 components inside your single-file component.

Here’s the newsletter that we created in the previous section, but class-based:

<?php

use Livewire\Volt\Component;

new class extends Component {
    public $email = '';
	
	public $done = false;
	
    $rules = ['email' => 'required|email'];
	
	public function submit() {
		$this->validate();

		// Subscribe the user.

		$this->done = true;
	};
};

?>

<div>
    @if ($done)
        <p>Thank you for subscribing!</p>
    @else
        <form wire:submit="submit">
            <input type="email" wire:model="email" required />

            <button>
                Subscribe
            </button>
        </form>

        @error('email')
            <p>{{ $message }}</p>
        @enderror
    @endif
</div>

How cool is that? And people not happy with the new declarative API will certainly be happy about class-based single file Volt components.

How to test our basic newsletter component

This hasn’t changed much if you are already familiar with writing Livewire tests. Let’s review how I wrote this test:

use Livewire\Volt\Volt;

it('can render', function () {
    $component = Volt::test('newsletter');
  
    $component
        // Test the initial state of the component.
        ->assertSet('email', '')
        ->assertSet('done', false)
        // Simulate the user entering an email address.
        ->set('email', 'homer@simpson.com')
        // Simulate the user submitting the form.
        ->call('submit')
        // Test the state properties have changed.
        ->assertSet('email', 'homer@simpson.com')
        ->assertSet('done', true)
        // Test the confirmation message is displayed.
        ->assertSee('Thank you for subscribing!');
  
    // There, you can also test that the user has been subscribed successfully.
});
  1. We render the component using Volt::test('newsletter').
  2. We test the initial state for the expected values.
  3. We simulate the user’s input and action.
  4. We test for the expected state.
  5. We test for the expected confirmation message to be displayed.
  6. We test that the user has been successfully subscribed.

All good? Now run php artisan test and enjoy the greenery and confidence tests give you!

Learn more about how to test Volt components on the official documentation.

Laravel Volt presented by Taylor Otwell

Oh, before I leave, I wanted to share with you the video from Laracon US where Taylor Otwell himself unveils and demos Laravel Volt (skip to 40:32). Enjoy!

Wait, there's more!

3 comments

polodev
polodev Modified 3mos ago

your laracast post inspired me to use volt and livewire3.

I have upgraded to livewire 3 from livewire 2. having a lot of livewire component

Want to use Volt.

But getting error in regular page/livewire page while adding App\Providers\VoltServiceProvider::class in config/app.php providers array.

Normal error like Undefined variable. Despite being variable defined.

for Example:

In a blade file I assigned a variable $hello = 'world'.

In very next line I am printing echo $hello.

Output undefined variable $hello.

just after adding App\Providers\VoltServiceProvider::class class.

If I comment/delete this provider from provider array everything working as expected

Alt text volt error

polodev
polodev 3mos ago

Finally got solution

inside volt service provider just added a different path specific to the volt. In my case it is views/livewire/volt

And remove main livewire resources path views/livewire

Volt::mount([
  resource_path('views/livewire/volt'), # it should be the top in case of multiple resource_path. can benefits from volt blade file creation using artisan command. it will select path automatically
]);

Make a volt file using artisan command

php artisan make:volt volt-test
# Output:   `INFO`  Volt component [resources/views/livewire/volt/volt-test.blade.php] created successfully.  

Inside route file

Volt::route('/volt-test', 'backend/volt-test')->name('volt.test');

Clear cached view

php artisan view:clear
# for all clear
# php artisan optimize:clear
Benjamin Crozat
Benjamin Crozat 3mos ago

Thanks for sharing your solution!

Get help or share something of value with other readers!

Great deals for enterprise developers
  • ZoneWatcher
    Get instant alerts on DNS changes across all major providers, before your customers notice.
    25% off for 12 months using the promo code CROZAT.
    Try ZoneWatcher for free
  • Quickly build highly customizable admin panels for Laravel projects.
    20% off on the pro version using the promo code CROZAT.
    Try Backpack for free
  • Summarize and talk to YouTube videos. Bypass ads, sponsors, chit-chat, and get to the point.
    Try Nobinge →
  • Monitor the health of your apps: downtimes, certificates, broken links, and more.
    20% off the first 3 months using the promo code CROZAT.
    Try Oh Dear for free
  • Keep the customers coming; monitor your Google rankings.
    30% off your first month using the promo code WELCOME30
    Try Wincher for free →
The latest community links
- / -