I have two tables under each over in Livewire component, what I'm trying to do is when I click on one of the roles the second table (permissions table) should refresh with the provided role permissions, one the first and second click it works perfectly but after that the permission table start become longer and some element start diaper,this is my Role controller:
<?php
use Livewire\Component;
use Spatie\Permission\Models\Role;
class RolesTable extends Component
{
public $permissions;
protected $listeners = ['refreash_permissions' => '$refresh'];
public function render()
{
$roles = Role::all();
return view('components.roles-table',compact(['roles' , $roles]));
}
public function get_permissions($role_id){
$this->emitSelf('refreash_permissions');
if($role = Role::findById($role_id)) {
$role = Role::findById($role_id);
$this->permissions = $role->permissions()->get();
}
}
}
and this is my view:
<div class="">
<div class="col-12 mb-3">
<p class="mx-2 h3">Roles :</p>
<table class="table table-hover table-inverse shadow-lg rounded-corners">
<thead class="thead-inverse">
<tr class="border-bottom">
<th class="mx-3 count">#</th>
<th class="mx-3 full-name" width="150px">Role Name</th>
<th class="mx-3 responsive-766" width="auto">Role Description</th>
<th class="mx-3 auctions d-flex justify-content-end mx-5" width="auto">Actions</th>
</tr>
</thead>
<tbody>
@foreach ($roles as $role)
<tr id="{{ $role->id }}" wire:click="get_permissions({{ $role->id }})" class="">
<td class="mx-3">{{ $loop->iteration }}</td>
<td class="">{{ $role->name }}</td>
<td id="{{ $role->description }}" class="description responsive-766">Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ducimus rem porro inventore nemo ad ratione aperiam minima necessitatibus excepturi provident sunt blanditiis quis tempore, pariatur dicta quidem nesciunt beatae, quia eaque? Ut .</td>
<td id='{{ $role->id }}' class="auction d-flex justify-content-end">
@can('view_roles')
<a id="{{ $role->id }}" class="role_profile btn btn-inv-info btn-sm m-1"><i class="fad fa-id-card fa-lg"></i></a>
@endcan
@can('edit_roles')
<a id="{{ $role->id }}" class="role_edit btn btn-inv-warning btn-sm m-1"><i class="fad fa-key fa-lg"></i></a>
@endcan
@can('delete_roles')
<a id="{{ $role->id }}" class="role_remove btn btn-inv-danger btn-sm m-1"><i class="fad fa-trash fa-lg"></i></a>
@endcan
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
<div class="col-12 mb-3">
<p class="mx-2 h3">Permissions :</p>
<table class="table table-hover table-inverse shadow-lg rounded-corners">
<thead class="thead-inverse">
<tr class="border-bottom">
<th class="mx-3 count">#</th>
<th class="mx-3 full-name" width="150px">Permission Name</th>
<th class="mx-3 responsive-766" width="auto">Permission Description</th>
<th class="mx-3 auctions d-flex justify-content-end mx-5" width="auto">Actions</th>
</tr>
</thead>
<tbody>
@if ($permissions)
@foreach ($permissions as $permission)
<tr id="{{ $permission->id }}" class="">
<td class="mx-3">{{ $loop->iteration }}</td>
<td class="">{{ $permission->name }}</td>
<td id="{{ $permission->description }}" class="description responsive-766">Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ducimus rem porro inventore nemo ad ratione aperiam minima necessitatibus excepturi provident sunt blanditiis quis tempore, pariatur dicta quidem nesciunt beatae, quia eaque? Ut .</td>
<td id='{{ $permission->id }}' class="auction d-flex justify-content-end">
@can('view_roles')
<a id="{{ $permission->id }}" class="permission_profile btn btn-inv-info btn-sm m-1"><i class="fad fa-id-card fa-lg"></i></a>
@endcan
@can('edit_roles')
<a id="{{ $permission->id }}" class="permission_edit btn btn-inv-warning btn-sm m-1"><i class="fad fa-key fa-lg"></i></a>
@endcan
@can('delete_roles')
<a id="{{ $permission->id }}" class="permission_remove btn btn-inv-danger btn-sm m-1"><i class="fad fa-trash fa-lg"></i></a>
@endcan
</td>
</tr>
@endforeach
@else
<tfoot>
<tr>
<td class="auto"></td>
<td class="auto"></td>
<td class="auto"></td>
<td width="auto d-flex justify-content-end text-center">there is nothing to show</td>
<td class="auto"></td>
<td class="auto"></td>
<td class="auto"></td>
</tr>
</tfoot>
@endif
</tbody>
</table>
</div>
</div>
this is also some screenshots: this before any click this after one or two clicks after that in any click, the table becomes link this: this when the thing become super weird any advice I will be thankful.
In your render method, you have the compact array:
public function render()
{
$roles = Role::all();
return view('components.roles-table',compact(['roles' , $roles]));
}
Ideally you should just pass compact('roles')
to the method.
secondly, you are doinh the following in your get_permissions
method
public function get_permissions($role_id)
{
$this->emitSelf('refreash_permissions');
if($role = Role::findById($role_id)) {
$role = Role::findById($role_id);
$this->permissions = $role->permissions()->get();
}
}
you're accessing the database twice. I would do this:
public function get_permissions($role_id)
{
$role = Role::findOrFail($role_id);
$this->permissions = $role->permissions;
$this->emitSelf('refreash_permissions');
}
You're emitting refreash_permissions
before you update the values.
Onto what is happening:
Firstly you're not providing Livewire
with a reference to the row which is creating an issue with the diff. https://laravel-livewire.com/docs/2.x/troubleshooting I would recommend assigning a wire:key
reference to the row, which is usually the Permission ID but in this case you're replacing the whole section so you should use the $loop->index()
value, and if Livewire
has multiple elements on the page, maybe prefix it with a string, such as 'permission.' . $loop->index()
to advise Livewire what element is referenced here.
Secondly, I would possibly rename the permissions parameter on the class rolePermissions
in order to prevent variable pollution with the compact()
method since you're passing an array with an array nesting.