Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

muuucho's avatar
Level 11

Livewire toggle to acitvate/de-activate a user

In my view of all team members, I like to have two toggling buttons, one for is_admin, and one for is_active. The is_admin toggling works but when I try to toggle is_active, the is_admin is changed. Why is that? UPDATE: When I click the circle of the icon it works, but if I click the other part of the icon, the problem appears. UsersList.php:

<?php

namespace App\Livewire;

use Auth;
use Livewire\Component;
use App\Models\User;
use Livewire\Attributes\On;
use Livewire\Attributes\Url;
use Illuminate\Contracts\View\View;
use Jantinnerezo\LivewireAlert\LivewireAlert;
use Livewire\WithPagination;

class UsersList extends Component
{
    use LivewireAlert;
    use WithPagination;

    public ?User $user = null;
    #public Collection $users;

    public array $selected = [];
    #[Url]
    public string $sortColumn = 'users.name';  // Default col to sort
    #[Url]
    public string $sortDirection = 'asc'; // Default sort order

    public array $active;
    public array $admin;
    public array $searchColumns = [
        'name' => '',
        'is_admin' => '',
        'email' => '',
        'is_active' => '',
    ];

    public function toggleIsAdmin(int $userId): void
    {
        User::where('id', $userId)->update([
            'is_admin' => $this->admin[$userId],
        ]);
    }
    public function toggleIsActive(int $userId): void
    {
        User::where('id', $userId)->update([
            'is_active' => $this->active[$userId],
        ]);
    }

    public function getSelectedCountProperty(): int
    {
        return count($this->selected);
    }
    public function deleteConfirm($method, $id = null): void
    {
        $this->dispatch('swal:confirm', [
            'type'  => 'warning',
            'title' => 'Are you sure?',
            'text'  => '',
            'id'    => $id,
            'method' => $method,
        ]);
    }
    #[On('delete')]
    public function delete(int $id): void
    {
        $pub = User::where('id', $id )->firstOrFail();
        $pub->delete();
    }
    #[On('deleteSelected')]
    public function deleteSelected(): void
    {
        $users = User::whereIn('id', $this->selected)->get();
        $users->each->delete();
        $this->reset('selected');
    }

    public function sortByColumn(string $column): void
    {
        if ($this->sortColumn == $column) {
            $this->sortDirection = $this->sortDirection == 'asc' ? 'desc' : 'asc';
        } else {
            $this->reset('sortDirection');
            $this->sortColumn = $column;
        }
    }

    public function render(): View
    {
        $usersQuery = User::query()
            ->select(['users.*']);
        foreach ($this->searchColumns as $column => $value) {
            if (!empty($value)) {
                $usersQuery
                    ->when($column === 'name', fn($query) => $query->where('users.' . $column, 'LIKE', '%' . $value . '%'))
                    ->when($column === 'email', fn($query) => $query->where('users.' . $column, 'LIKE', '%' . $value . '%'))
                    ->when($column === 'is_admin', fn($query) => $query->where('users.' . $column, '=', $value-1))
                    ->when($column === 'is_active', fn($query) => $query->where('users.' . $column, '=', $value-1));
            }
        }
        $usersQuery->where('team_id', '=', auth()->user()->team_id);

        $usersQuery->orderBy($this->sortColumn, $this->sortDirection);
        $users = $usersQuery->get();

        $this->admin = $users->mapWithKeys(
            fn (User $item) => [$item['id'] => (bool) $item['is_admin']]
        )->toArray();

        $this->active = $users->mapWithKeys(
            fn (User $item) => [$item['id'] => (bool) $item['is_active']]
        )->toArray();

        return view('livewire.users-list',  [
            'users' => $usersQuery->paginate(10)
        ]);
    }
}

users-list.blade.php

<div>
     <x-slot name="header">
          <h2 class="text-xl font-semibold leading-tight text-gray-800">
               {{ __('Users') }}
          </h2>
     </x-slot>
     <div class="py-12">
          <div class="mx-auto max-w-7xl sm:px-6 lg:px-8">
               <div class="overflow-hidden bg-white shadow-sm sm:rounded-lg">
                    <div class="p-6 bg-white border-b border-gray-200">
                         <div class="mb-4">
                              <div class="mb-4">
                                   <a href="{{ route('invitations.index') }}" class="inline-flex items-center px-4 py-2 text-xs font-semibold tracking-widest text-white uppercase bg-gray-800 rounded-md border border-transparent hover:bg-gray-700">
                                        Invites
                                   </a>
                              </div>
                              <button type="button"
                                      wire:click="deleteConfirm('deleteSelected')"
                                      wire:loading.attr="disabled"
                                      @disabled(! $this->selectedCount)
                                      class="px-4 py-2 mr-5 text-xs text-red-500 uppercase bg-red-200 rounded-md border border-transparent hover:text-red-700 hover:bg-red-300 disabled:opacity-50 disabled:cursor-not-allowed">
                                   Delete Selected
                              </button>
                         </div>
                         <div class="overflow-hidden overflow-x-auto mb-4 min-w-full align-middle sm:rounded-md">
                              <table class="min-w-full border divide-y divide-gray-200">
                                   <thead>
                                   <tr>
                                        <th class="px-6 py-3 text-left bg-gray-50">
                                        </th>
                                        <th wire:click="sortByColumn('users.name')" class="px-6 py-3 text-left bg-gray-50">
                                             <span class="text-xs font-medium tracking-wider leading-4 text-gray-500 uppercase">Name</span>
                                             @if ($sortColumn == 'users.name')
                                                  @include('svg.sort-' . $sortDirection)
                                             @else
                                                  @include('svg.sort')
                                             @endif
                                        </th>
                                        <th wire:click="sortByColumn('users.email')" class="px-6 py-3 text-left bg-gray-50">
                                             <span class="text-xs font-medium tracking-wider leading-4 text-gray-500 uppercase">Email</span>
                                             @if ($sortColumn == 'users.email')
                                                  @include('svg.sort-' . $sortDirection)
                                             @else
                                                  @include('svg.sort')
                                             @endif
                                        </th>
                                        <th class="px-6 py-3 text-left bg-gray-50">
                                             <span class="text-xs font-medium tracking-wider leading-4 text-gray-500 uppercase">Admin</span>
                                        </th>
                                        <th class="px-6 py-3 text-left bg-gray-50">
                                             <span class="text-xs font-medium tracking-wider leading-4 text-gray-500 uppercase">Active</span>
                                        </th>
                                   </tr>
                                   <tr>
                                        <td></td>
                                        <td class="px-2 py-2">
                                             <input wire:model.live.debounce="searchColumns.name" type="text" placeholder="Search..."
                                                    class="w-full text-sm rounded-md border-gray-300 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50" />
                                        </td>
                                        <td class="px-2 py-2">
                                             <input wire:model.live="searchColumns.email" type="text" placeholder="Search..."
                                                    class="w-full text-sm rounded-md border-gray-300 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50" />
                                        </td>
                                        <td class="px-2 py-1">
                                            {{-- <select wire:model.live="searchColumns.is_admin"
                                                     class="w-full text-sm rounded-md border-gray-300 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50">
                                                  <option value="">choose...</option>
                                                  @foreach($is_admins as $id => $is_admin)
                                                       <option value="{{ $id }}">{{ $is_admin }}</option>
                                                  @endforeach
                                             </select>--}}
                                        </td>
                                        <td class="px-2 py-1">
                                            {{-- <select wire:model.live="searchColumns.is_admin"
                                                     class="w-full text-sm rounded-md border-gray-300 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50">
                                                  <option value="">choose...</option>
                                                  @foreach($is_admins as $id => $is_admin)
                                                       <option value="{{ $id }}">{{ $is_admin }}</option>
                                                  @endforeach
                                             </select>--}}
                                        </td>
                                   </tr>
                                   </thead>
                                   <tbody class="bg-white divide-y divide-gray-200 divide-solid">
                                   @foreach($users as $user)
                                        <tr class="bg-white" wire:key="{{ $user->id }}">
                                             <td class="px-4 py-2 text-sm leading-5 text-gray-900 whitespace-no-wrap">
                                                  <input type="checkbox" value="{{ $user->id }}" wire:model.live="selected">
                                             </td>
                                             <td class="px-6 py-4 text-sm leading-5 text-gray-900 whitespace-no-wrap">
                                                  {{ $user->name }}
                                             </td>
                                             <td class="px-6 py-4 text-sm leading-5 text-gray-900 whitespace-no-wrap">
                                                  {{ $user->email }}
                                             </td>
                                             <td class="px-6">
                                                  <div class="inline-block relative mr-2 w-10 align-middle transition duration-200 ease-in select-none">
                                                       <input wire:model="admin.{{ $user->id }}" wire:click="toggleIsAdmin({{ $user->id }})" type="checkbox" name="toggle" id="{{ $loop->index.$user->id }}" class="block absolute w-6 h-6 bg-white rounded-full border-4 appearance-none cursor-pointer focus:outline-none toggle-checkbox" />
                                                       <label for="{{ $loop->index.$user->id }}" class="block overflow-hidden h-6 bg-gray-300 rounded-full cursor-pointer toggle-label"></label>
                                                  </div>
                                             </td>
                                             <td class="px-6">
                                                  <div class="inline-block relative mr-2 w-10 align-middle transition duration-200 ease-in select-none">
                                                       <input wire:model="active.{{ $user->id }}" wire:click="toggleIsActive({{ $user->id }})" type="checkbox" name="toggle2" id="{{ $loop->index.$user->id }}" class="block absolute w-6 h-6 bg-white rounded-full border-4 appearance-none cursor-pointer focus:outline-none toggle-checkbox" />
                                                       <label for="{{ $loop->index.$user->id }}" class="block overflow-hidden h-6 bg-gray-300 rounded-full cursor-pointer toggle-label"></label>
                                                  </div>
                                             </td>
                                        </tr>
                                   @endforeach
                                   </tbody>
                              </table>
                         </div>
                         {{ $users->links() }}
                    </div>
               </div>
          </div>
     </div>
</div>
0 likes
3 replies
muuucho's avatar
muuucho
OP
Best Answer
Level 11

SOLVED: I changed the is_active button to this:

<td class="px-6">
                                                  <div class="inline-block relative mr-2 w-10 align-middle transition duration-200 ease-in select-none">
                                                       <input wire:model="active.{{ $user->id }}" wire:click="toggleIsActive({{ $user->id }})" type="checkbox" name="toggle2" id="{{ $loop->index.$user->id.'2' }}" class="block absolute w-6 h-6 bg-white rounded-full border-4 appearance-none cursor-pointer focus:outline-none toggle-checkbox" />
                                                       <label for="{{ $loop->index.$user->id.'2' }}" class="block overflow-hidden h-6 bg-gray-300 rounded-full cursor-pointer toggle-label"></label>
                                                  </div>
                                             </td>
```			
Snapey's avatar

Where are your wire:key's ?

Please or to participate in this conversation.