skip to Main Content

When nested boolean property values (e.g. nested.value) of a Livewire component change, checkboxes do not change their checked state.

Here is a wirebox with the scenario: https://wirebox.app/b/x58lv
Initial state is correct. When a model is loaded, the checked states do not change.
The checkboxes with not nested values work.

This occurs for example when I use Livewire Form Objects.
No problem with not nested values.

<?php
namespace AppLivewire;

use LivewireComponent;
use AppModelsBoolModel;

class Simple extends Component
{
    public $bools = [
        'one' => true,
        'two' => false,
    ];

    public string $name = 'none';

    public bool $one = true;
    public bool $two = false;
    
    public function render()
    {
        return view('livewire.simple');
    }

    public function load($id)
    {
        $model = BoolModel::find($id);
        
        $this->name = $model->name;
        
        $this->bools = [
            'one' => $model->one,
            'two' => $model->two,
        ];
        
        $this->one = $model->one;
        $this->two = $model->two;
    }
}
<div>
    <h1 class="text-white">{{ $name }}</h1>
    <div class="flex w-full h-full items-center justify-center text-gray-300 px-16">
        <div class="text-light me-3">Array:</div> 
        <input type="checkbox" wire:model.blur="bools.one" /><span class="mx-2"> :: {{$bools['one'] ? 'true' : 'false'}}</span>
        <input type="checkbox" wire:model.blur="bools.two" /><span class="mx-2"> :: {{$bools['two'] ? 'true' : 'false'}}</span>
    </div>
    <div class="flex w-full h-full items-center justify-center text-gray-300 px-16">
        <div class="text-light me-3">single:</div> 
        <input type="checkbox" wire:model.blur="one" /><span class="mx-2"> :: {{$one ? 'true' : 'false'}}</span>
        <input type="checkbox" wire:model.blur="two" /><span class="mx-2"> :: {{$two ? 'true' : 'false'}}</span>
    </div>
        <div>
    <button class="bg-white" role="button" wire:click="load(1)">load 1</button>
    <button class="bg-white" role="button" wire:click="load(2)">load 2</button>
        </div>
</div>

2

Answers


  1. Please try it yourself and let me know if you have any questions.
    https://wirebox.app/b/xgddk

    Login or Signup to reply.
  2. Laravel Sushi (which you are using in your Wirebox example) converts booleans to integers by default as many DBMS engines do

    To verify this behaviour you can replace the ternary operators in the <span> tags of the view with var_export() which output the real values of the variables:

    <!--<span class="mx-2"> :: {{$bools['one'] ? 'true' : 'false'}}</span>-->
    <span class="mx-2"> :: {{var_export($bools['one'], true)}}</span>
    
    <!--<span class="mx-2"> :: {{$bools['two'] ? 'true' : 'false'}}</span>-->
    <span class="mx-2"> :: {{var_export($bools['two'], true)}}</span>
    
    <!--<span class="mx-2"> :: {{$one ? 'true' : 'false'}}</span>-->
    <span class="mx-2"> :: {{var_export($one, true)}}</span>
    
    <!--<span class="mx-2"> :: {{$two ? 'true' : 'false'}}</span>-->
    <span class="mx-2"> :: {{var_export($two, true)}}</span>
    

    When you assign the integer to non-array properties that are defined as bools in your class, e.g.: public bool $one = true;, an implicit cast is performed and the numeric values are converted to booleans.
    On the other hand this conversion is not performed automatically when these values are assigned to the items of the associative array

    When Livewire assigns values ​​to checkboxes it evidently checks the boolean values ​​strictly and if it receives non-boolean values ​​(such as 0 or 1) it cannot set the checks correctly

    Solution:
    To obtain the correct behaviour for the values which are elements of an associative array you can add casts in your model:

    protected $casts = [
        'one' => 'boolean',
        'two' => 'boolean'
    ];
    

    in this way the properties of the model will contain boolean values and the arrays will receive booleans too

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search