My Blade view for Livewire component:
<div>
<input type="checkbox" class="form-checkbox" wire:model="inner_checked" wire:click="toggleChecked">
@if ($inner_checked)
inner checked
@else
inner unchecked
@endif
</div>
Works good - printed exactly according to checkbox state.
Then use this component at outer level:
<livewire:form-checkbox :id="$id" :checked=$outer_checked />
@if ($outer_checked)
Outer checked
@else
Outer unchecked
@endif
Works bad - outer state printed well according to initial value of $outer_checked
, but changes inside checkbox not populated to outside.
Ok, rewrite mount(string $id, bool $outer_checked)
to just mount(string $id)
and rewrite usage of checkbox component to <livewire:form-checkbox :id="$id" wire:model=$outer_checked />
. Still no changes - internal state changed, outer - not. Guess it's because wire:model
not working here, at outer level.
How to populate internal state changes to outer level?
You'd need to use an event, dispatching it from the child (inner) and listening for it on the parent (outer)
use Livewire\Attributes\On;
class OuterComponent
{
public bool $outer_checked;
#[On('inner-state-updated')]
public function applyChangesToOuterState(bool $value)
{
$this->outer_checked = $value;
}
}
class InnerComponent
{
public bool $inner_checked;
public function updated($property)
{
if ($property === 'inner_checked') {
$this->dispatch('inner-state-updated', value: $this->inner_checked);
}
}
// alternatively
public function updatedInnerChecked()
{
$this->dispatch('inner-state-updated', value: $this->inner_checked);
}
}
Alternatively, if you can hook into this change from the javascript side, you could access the parent's property and set it there with $parent
.