Livewire - how to update value based on user click? Here are five ways how to do it!
Let's say you want to update a component ( nested or not ) when user click on a button. In some cases you can face an issue that child component is calling a method in parent component or that clicking in :wire:click is not responding and here i will explain how to fix it.
How to update livewire component value on click
OK, let's say we have a livewire class where we want to update a value, in our case we want to show or hide modal window. In our case we will be using Laravel jetstream modal but this can be applied on plane laravel blade components as well.
So let's create our livewire model:
php artisan livewire:make CustomModal
this will create two files, PHP class and blade component
/* CustomModal.php */
namespace App\Http\Livewire;
use Livewire\Component;
class CustomModal extends Component
{
public $showingModal = false;
public $listeners = [
'hideMe' => 'hideModal'
];
public function render()
{
return view('livewire.custom-modal');
}
public function showModal(){
$this->showingModal = true;
}
public function hideModal(){
$this->showingModal = false;
}
}
in our Laravel blade component we will create a button to open the modal and once it is open we will create a button inside of it to close it:
<!-- custom-modal.blade.php -->
<div>
<!-- on click show modal -->
<div wire:click="showModal" wire:loading.attr="disabled" class="p-4 text-gray-900 cursor-pointer">
Open modal
</div>
<x-jet-dialog-modal wire:model="showingModal" >
<x-slot name="title">
Modal custom title
</x-slot>
<x-slot name="content">
<p>Test modal content</p>
</x-slot>
</x-jet-dialog-modal>
</div>
Our modal is ready to be used, when user click on a button "Open Modal" modal window will open. The only thing that we need to do is include it in our page:
<livewire:custom-modal :wire:key="'custom-modal-'.time()">
As you can see we are adding wire key, this will solve the problems if this livewire model is used as nested component in another livewire model.
Now we can add different ways to close modal window, here are 5 examples how to do it:
<x-slot name="footer">
<x-jet-secondary-button wire:click="hideModal" wire:loading.attr="disabled">
{{ __('Cancel') }} hidefn
</x-jet-secondary-button>
<x-jet-secondary-button wire:click="$set('showingModal', false)" wire:loading.attr="disabled">
{{ __('Cancel') }} set
</x-jet-secondary-button>
<x-jet-secondary-button wire:click="$emitSelf('hideMe')" wire:loading.attr="disabled">
{{ __('Cancel') }} emitSelf
</x-jet-secondary-button>
<x-jet-secondary-button wire:click="$emitTo('custom-modal', 'hideMe')" wire:loading.attr="disabled">
{{ __('Cancel') }} emitTo
</x-jet-secondary-button>
<x-jet-secondary-button wire:click="$toggle('showingModal')" wire:loading.attr="disabled">
{{ __('Cancel') }} toggle
</x-jet-secondary-button>
</x-slot>
and here is another example, if you use alpine:
<x-jet-secondary-button x-on:click="show = false" wire:loading.attr="disabled">
{{ __('Cancel') }} alpine
</x-jet-secondary-button>
So our, custom-modal blade file will look like this:
<!-- custom-modal.blade.php -->
<div>
<!-- on click show modal -->
<div wire:click="showModal" wire:loading.attr="disabled" class="p-4 text-gray-900 cursor-pointer">
Open modal
</div>
<x-jet-dialog-modal wire:model="showingModal" >
<x-slot name="title">
Modal custom title
</x-slot>
<x-slot name="content">
<p>Test modal content</p>
</x-slot>
</x-jet-dialog-modal>
<x-slot name="footer">
<x-jet-secondary-button wire:click="hideModal" wire:loading.attr="disabled">
{{ __('Cancel') }} hidefn
</x-jet-secondary-button>
<x-jet-secondary-button wire:click="$set('showingModal', false)" wire:loading.attr="disabled">
{{ __('Cancel') }} set
</x-jet-secondary-button>
<x-jet-secondary-button wire:click="$emitSelf('hideMe')" wire:loading.attr="disabled">
{{ __('Cancel') }} emitSelf
</x-jet-secondary-button>
<x-jet-secondary-button wire:click="$emitTo('custom-modal', 'hideMe')" wire:loading.attr="disabled">
{{ __('Cancel') }} emitTo
</x-jet-secondary-button>
<x-jet-secondary-button wire:click="$toggle('showingModal')" wire:loading.attr="disabled">
{{ __('Cancel') }} toggle
</x-jet-secondary-button>
</x-slot>
</div>
🥬
Additional: how to use Laravel JetStream modal window based on livewire: