Search code examples
phplaravellaravel-livewire

Keep selected checkboxes in child foreach loop when a new array is added with a parent and child foreach loop - Laravel livewire


We have a form that allows the admins to select a role from the dropdown menu and then shows the users associated with that role which can be selected. At the same time, you can add multiple roles in the same form.

When you add another role, the user's selected in the previous role list disappears and loses the selected users.

preview of snippet

We think that we need to do something in the updatedSelectedRole method in the Livewire component but we are not sure what. The $roleSelectedUserList gets re-rendered to an empty array when adding another role.

Livewire component

namespace App\Http\Livewire\Admin;

use App\Models\Role;
use App\Models\User;
use Livewire\Component;

class Create extends Component
{
    public $roleSelectedUserList = [];
    public $selected_role_user = [];
    public $selected_role = [];
    public $rolesList = [];
    public $roles = [];

    public function updatedSelectedRole($name, $value)
    {
        $this->roleSelectedUserList = User::join('role_user', 'users.id', '=', 'role_user.user_id')
            ->select('users.*')
            ->where('role_user.role_id', $name)
            ->get();
    }

    public function addDataColumn()
    {
        $this->roleSelectedUserList = [];
        $this->selected_role_user = [];
        $this->roles[] = [[]];
    }

    public function mount()
    {
        $this->rolesList = Role::pluck('name', 'id');
        $this->roles = [[]];
    }

    public function render()
    {
        return view('livewire.users.create');
    }
}

The Blade File

<div class="row">
   <div class="col-md-12">
      @foreach($roles as $index => $role)
          <div class="form-group row mb-0" wire:key="div-{{ $loop->index }}">
             <div class="col-lg-12">
                <div class="form-group row">
                  <div class="col-md-6">
                     <div class="form-group">
                         <label for="type">Roles *</label>
                         <select class="form-control form-control-lg form-control-solid"  wire:model="selected_role.{{$index}}" id="selected_role.{{$index}}" name="selected_role.{{$index}}">
                            @foreach($rolesList as $key => $role)
                               <option value="{{ $key }}">{{ $role }}</option>
                            @endforeach
                         </select>
                      </div>
                   </div>
                   <div class="col-md-4">
                       <div class="">
                          <div class="form-group">
                              @foreach($roleSelectedUserList as $user)
                                   <input wire:model="selected_role_user.{{$user->id}}" type="checkbox" id="selected_role_user.{{$user->id}}" name="selected_role_user.{{$user->id}}"/>                                         
                                   {{$user->first_name}}                                   
                              @endforeach
                           </div>
                        </div>
                     </div>
                  </div>
              </div>
           </div>
           @endforeach
           <div class="form-group row">
              <div class="col-lg-4">
                 <button wire:click.prevent="addDataColumn" type="button" class="btn btn-primary btn-sm font-weight-bolder mt-lg-0 mt-20">
                      <i class="la la-plus"></i>{!! trans('global.button.add') !!}
                 </button>
              </div>
           </div>
        </div>
   </div>

Solution

  • You can change the code as below:

    <div class="row">
        <div class="col-md-12">
            @foreach($roles as $index => $role)
            <div class="form-group row mb-0" wire:key="div-{{ $loop->index }}">
                <div class="col-lg-12">
                    <div class="form-group row">
                        <div class="col-md-6">
                            <div class="form-group">
                                <label for="type">Roles *</label>
                                <select class="form-control form-control-lg form-control-solid"
                                    wire:model="selected_role.{{$index}}" id="selected_role.{{$index}}"
                                    name="selected_role.{{$index}}">
                                    @foreach($rolesList as $key => $role)
                                    <option value="{{ $index }},{{ $key }}">{{ $role }}</option>
                                    @endforeach
                                </select>
                            </div>
                        </div>
                        <div class="col-md-4">
                            <div class="">
    
                                <div class="form-group">
                                    @isset($roleSelectedUserList[$index])
                                    @foreach($roleSelectedUserList[$index] as $user)
                                    <input wire:model="selected_role_user.{{$index}}" type="checkbox"
                                        value="{{$user['id'] }}" />
                                    {{$user['first_name']}}{{$index}}
                                    @endforeach
                                    @endisset
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            @endforeach
            <div class="form-group row">
                <div class="col-lg-4">
                    <button wire:click.prevent="addDataColumn" type="button"
                        class="btn btn-primary btn-sm font-weight-bolder mt-lg-0 mt-20">
                        <i class="la la-plus"></i>{!! trans('global.button.add') !!}
                    </button>
                </div>
            </div>
        </div>
    </div>
    
        public $roleSelectedUserList = [];
        public $selected_role_user = [];
        public $selected_role = [];
        public $rolesList = [];
        public $roles = [];
    
        public function updatedSelectedRole($value)
        {
            $arryValue = explode(",", $value);
            $index = $arryValue[0];
            $id = $arryValue[1];
     
            $this->roleSelectedUserList[$index] = User::join('role_user', 'users.id', '=', 'role_user.user_id')
                ->select('users.*')
                ->where('role_user.role_id', $id)
                ->get();
    
            $this->selected_role_user[$index] = [];
        }
    
        public function addDataColumn()
        {
            $this->roles[] = [[]];
    
            $this->selected_role[] = [];
            $this->selected_role_user[] = [];
        }
    
        public function mount()
        {
            $this->rolesList = Role::pluck('name', 'id');
             
            $this->roles[] = [];
             
            $this->selected_role_user[] = [];
            $this->selected_role[] = [];
        }
    
        public function render()
        {
            return view('livewire.users.create');
        }