How to Use Loading State in Laravel Livewire

In this section, we will see a loading circle animation after submitting a form in Laravel Livewire. To achieve this, we will utilize Livewire Loading States. The wire:loading directive is particularly useful, as it is only visible while waiting for a network action to complete.

Use sleep() function in livewire component

The sleep() function delays execution of the current script for a specified number of seconds.

Livewire Component File

<?php

namespace App\Http\Livewire;

use App\Models\Post;
use Livewire\Component;
use Livewire\WithPagination;

class PostForm extends Component
{
    use WithPagination;

    public $title;
    public $description;
    public $post_id;

    protected $rules = [
        'title' => 'required',
        'description' => 'required',
    ];

    public function storePost()
    {
        $this->validate();
        $post = Post::create([
            'title' => $this->title,
            'description' => $this->description
        ]);
        // delay  
        sleep(3);
        $this->reset();
        session()->flash('message', 'Post created successfully.');
    }

    public function render()
    {
        return view('livewire.post-form', ['posts' => Post::latest()->paginate(10)]);
    }
}

Livewire Component View File

You can use wire:loading alone or in combination with wire:target. I suggest using wire:loading with wire:target as it makes the code more readable.

Loading Button ui

<span class="inline-flex rounded-md shadow-sm">
    <button type="submit" class="inline-flex items-center px-4 py-2 text-base font-medium leading-6 text-white transition duration-150 ease-in-out bg-blue-600 border border-transparent rounded-md hover:bg-blue-500 focus:border-blue-700 active:bg-blue-700">
        <svg wire:loading class="w-5 h-5 mr-3 -ml-1 text-white animate-spin" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
            <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
            <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
        </svg>
        Submit
    </button>
</span>
Loading State After Submitting Form

resources/views/livewire/your-component.blade.php

<div>
    <h4 class="mb-4 text-2xl font-bold">Post</h4>
    @if (session()->has('message'))
    <div class="px-4 py-4 text-white text-green-800 bg-green-200 border-l-4 border-green-900 rounded">
        {{ session('message') }}
    </div>
    @endif
    <div>
        <div class="container mx-auto">
            <form method="POST" wire:submit.prevent="storePost">
                @csrf
                <div>
                    <label for="title">Title</label>
                    <input type="text" wire:model.lazy="title" class="w-full py-2 rounded" />
                    @error('title')
                    <span class="text-red-600">{{ $message }}</span>
                    @enderror
                </div>
                <div class="mt-8">
                    <label class="block mb-2 text-xl">Description </label>
                    <textarea wire:model.lazy="description" rows="3" cols="20" class="w-full rounded">
                    </textarea>
                    @error('description')
                    <span class="text-red-600">{{ $message }}</span>
                    @enderror
                </div>
                <div class="flex">
                    <span class="inline-flex rounded-md shadow-sm">
                        <button type="submit"
                            class="inline-flex items-center px-4 py-2 text-base font-medium leading-6 text-white transition duration-150 ease-in-out bg-blue-600 border border-transparent rounded-md hover:bg-blue-500 focus:border-blue-700 active:bg-blue-700">
                            <svg wire:loading wire:target="storePost" class="w-5 h-5 mr-3 -ml-1 text-white animate-spin"
                                xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
                                <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor"
                                    stroke-width="4"></circle>
                                <path class="opacity-75" fill="currentColor"
                                    d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z">
                                </path>
                            </svg>
                            Submit
                        </button>
                    </span>
                </div>
            </form>
        </div>
    </div>
</div>

If you want to show loading indicators only for specific actions.

<div>
  <button wire:click="activeUser">Show</button>
 
  <div wire:loading wire:target="activeUser">
    Processing ...
  </div>
</div>

Delaying loading indicator

You can customize the delay duration with the following modifier.

<div wire:loading.delay.shortest>...</div> <!-- 50ms -->
<div wire:loading.delay.shorter>...</div>  <!-- 100ms -->
<div wire:loading.delay.short>...</div>    <!-- 150ms -->
<div wire:loading.delay>...</div>          <!-- 200ms -->
<div wire:loading.delay.long>...</div>     <!-- 300ms -->
<div wire:loading.delay.longer>...</div>   <!-- 500ms -->
<div wire:loading.delay.longest>...</div>  <!-- 1000ms -->