In this Article, we will see how to customize our Button to have following Animation using Livewire and extract everything into a Blade Component so as to reuse anywhere into your application.
We are going to use the Breeze Button Component and extend it according to our needs. Its definition looks like below:
<button {{ $attributes->merge(['type' => 'submit']) }}>
{{ $slot }}
</button>
I have removed all the CSS Classes for clarify.We can use this Button Component inside our Livewire Component like below:
<x-button wire:click="save" wire:loading.attr="disabled">
Save
</x-button>
What we want is that whenever this button is clicked, we want to change the Text to Saving. In order to do that we will use the wire:loading
property.
<x-button wire:click="save" wire:loading.attr="disabled">
Save
<span wire:loading>Saving..</span>
</x-button>
So now "Saving.." will get displayed as long as the submit button is clicked. And it will get hidden when the AJAX Call has finished. However, during this AJAX Call both "Save" and "Saving.." are showing. So we also need to hide the "Save" during this AJAX Call. We can do so using wire:loading.remove
<x-button wire:click="save" wire:loading.attr="disabled">
<span wire:loading.remove>Save</span>
<span wire:loading>Saving..</span>
</x-button>
Now, even though this is working, this will lead to unexpected issues when you have more than 1 button on the Page. So it is always a good practice to specify that we only want to change the display of these elements when the AJAX Call corresponding to save method is being called. We can do so using wire:target
.
<x-button wire:click="save" wire:loading.attr="disabled">
<span wire:loading.remove wire.target="save">Save</span>
<span wire:loading wire.target="save">Saving..</span>
</x-button>
At this stage, you should see your buttons having the same behaviour as shared at the start of the Article. However, we can further improve the readability of our code by extracting the code to our Button Component. We want this to be as simple as following:
<x-button wire:click="save" loading="Saving..">
Save
</x-button>
First of all we will create a loading
property in our button component and assign it a default value of false
.
@props(['loading' => false])
We can read the Livewire Attributes inside our Blade Component using below code:
$attributes->wire('click')->value()
You can read more about them in the Livewire Docs.
When both loading
property is present and the wire:click
attribute is present, we want to insert our span tags, otherwise we will just display the Slot. So our Blade Components becomes like this.
@props(['loading' => false])
<button {{ $attributes->merge(['type' => 'submit']) }}>
@if ($loading && $target = $attributes->wire('click')->value())
<span wire:loading.remove wire:target="{{$target}}">{{$slot}}</span>
<span wire:loading wire:target="{{$target}}">{{$loading}}</span>
@else
{{ $slot }}
@endif
</button>
So now we can use our Button Component using the loading attributes as well as without the loading attribute.
Hope you have enjoyed this tutorial. For similar articles, you can follow me on Twitter
Top comments (0)