In this section we will see loading circle animation after submitting form in laravel livewire. To do this we will use livewire Loading States, livewire wire:loading is useful directive it only visible while waiting network action is 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 only or use wire:loading with wire:target. I suggest you to use wire loading with wire target it 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>
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 -->