Laravel LiveWire | Create a Simple Counter Web Application

Laravel Livewire package is an amazing tool that removes the pain for a developer working with javascript in laravel framework. This package provides components that make developing dynamic frontend interface in laravel framework easier as developers who don’t have enough experience in javascript can also build a web application which feels like they are built using Javascript which they are actually not.

Not to be confused with Livewire as replacement tools for React js or Vue js because for updating each state an ajax call is made to laravel application backend and that will update the value and new response will be sent back via ajax.

Installation and Configuration

For installation of livewire package using below command.

 composer require livewire/livewire

Your output looks like this shown below. And after successfully installation composer.json file will be updated with "livewire/livewire": "^1.0".
Laravel Livewire composer install terminal output

For customization of livewire setting, you may wish to run publish command and this will create config/livewire.php where you can specify a custom namespace for component class, view and assets path, which middleware to use and etc.

php artisan vendor:publish --tag=livewire:config

In livewire docs, it is recommended to add below script into the  composer.json file under scripts. This is to automatically update livewire assets with upcoming versions.

{
    "scripts": {
        "post-autoload-dump": [
            "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
            "@php artisan package:discover --ansi",
            "@php artisan vendor:publish --force --tag=livewire:assets --ansi"
        ]
    }
}

In .env you must specify APP_URL and this will be used to specify livewire to include assets from URL specified in asset_url of file config/livewire.php.

APP_URL=http://127.0.0.1/laravel_app/public

Update asset_url of config/livewire.php as shown below.

[
    ...

    'asset_url'  => env('APP_URL', null),
]

Developing a Counter Application

Create a Counter Component

Run make:livewire a command followed by the component class name.

php artisan make:livewire Counter

This command will generate a component file at app/Http/Livewire/Counter.php and also a view file for the component at resources/views/livewire/counter.blade.php.

You are free to rearrange the component class and view file into any directory you wish to. So for proper arrangement, I’ll move counter.blade.php inside folder resources/views/livewire/counter-views/.

This is how empty component Counter.php looks like.

<?php

namespace App\Http\Livewire;

use Livewire\Component;

class Counter extends Component
{

    public function render()
    {
        return view('livewire.counter'); 
    }
}    

Since we have moved our counter.blade.php file. You have to change the view path from livewire.counter to livewire.counter-views.counter.

In component Counter.php make below-shown modifications.

//Change 
return view('livewire.counter'); 

// to this
return view('livewire.counter-views.counter'); 

Including Livewire Assets

In resources/views/livewire/counter-views/base.blade.php.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Laravel LiveWire Counter Web Application</title>
    @livewireStyles
</head>
<body>
    @livewire('counter') <!-- Here you are importing component not view  -->
    
    @livewireScripts
</body>
</html>

Routing

In routes/web.php add a counter route which returns base.blade.php view.

// Live Wire Counter App
Route::get('counter', function(){
    return view('livewire.counter-views.base', []);
});

Update view resources/views/livewire/counter-views/counter.blade.php to below show.

<div>

    <h2>Laravel Livewire Counter Web Application</h2>

    @if ( session()->has('info') )
        <p><strong>Info : </strong> {{ session('info') }}</p>
    @endif

    <button type="button" wire:click="increament" >Increament</button>
    <input type="number" wire:model="initial" value="" readonly >
    <button type="button" wire:click="decreament" >Decrement</button>

    <hr>

    <form wire:submit.prevent="counterForm">
        <label for="">Enter Counter Starting Number</label><br>
        <input type="text" wire:model.lazy="starting_counter_number" value=""><br>
        @error('starting_counter_number')
            <span style="color:red">{{ $message }}</span> 
        @enderror
        <br>
        <input type="submit" value="Submit">
    </form>
</div>    

In the above snippet, you can notice two-button increment and decrement and when you click on them the value in the text box will be updated the component code is shown below.

public $initial = 0;

public function increament(){
    $this->initial+=1;
}

public function decreament(){
    if($this->initial>0){
        $this->initial-=1;
    }else{
        session()->flash('info', "You cannot have negative value in counter");
    }
}

The variable $initial is the initial value given to the input field <input readonly="readonly" type="number" value="" />. Adding wire:model="initial" will automatically update the value inside the input field with the current value assigned to a variable $initial.

Similarly, wire:click="increament" and wire:click="decreament" on the button will trigger increament() and decreament method of the component class.

And for form submission and preventing reload when clicked on submit, button use wire:submit.prevent="method_name_here_withour_brackets" will trigger prevent the form from submitting and trigger the method counterForm. You can also validate user-submitted form data using the validate() method.

And for displaying validation error use @error('field_name') {{ $message }} @enderror. The variable $message is not declared in the component but it displays validation error message of that particular field.
The counterForm() method code is given below.

public function counterForm(){

    $validated_data = $this->validate([
        "starting_counter_number" => "required|integer|gte:0",
    ]);

    $num = $validated_data["starting_counter_number"];

    $this->initial = $num;
}

Update Counter component by below snippet.

<?php

namespace App\Http\Livewire;

use Livewire\Component;
use Log;

class Counter extends Component
{

    public $initial = 0;

    public $starting_counter_number=NULL;

    public function increament(){
        $this->initial+=1;
    }

    public function decreament(){
        if($this->initial>0){
            $this->initial-=1;
        }else{
            session()->flash('info', "You cannot have negative value in counter");
        }
    }

    public function counterForm(){

        $validated_data = $this->validate([
            "starting_counter_number" => "required|integer|gte:0",
        ]);

        $num = $validated_data["starting_counter_number"];

        $this->initial = $num;
    }

    public function render()
    {
        return view('livewire.counter-views.counter'); 
    }
}

The render() is called when the view is reloaded and also on each request has it must update the DOM content.

Result

Now you have followed all the above steps and here is the video of the final output of your counter application.

Conclusion

In conclusion, you have understood the basics of Laravel Livewire and you have also learnt how to create a simple counter application. In future, we’ll be posting an article on creating a dynamic application using livewire with real-life project examples so that you can understand its applications.

Goto livewire website to explore Livewire documentation.

Related Posts

For question and request on tutorials comment below or contact us. Our team will be delighted to receive any kind of appreciation, queries and suggestions.

Summary