Modals for paginated users

Hey guys,

I have a table of users which are paginated and each user will have an ‘edit’ button which displays a modal. What are the best practices for including this? Here is a minimal example.

                <table class="table">
                <tr>
                    <td>Name</td>
                    <td>Actions</td>
                </tr>
                @foreach($users as $key => $user)
                    <tr id="{{ $user->id }}">
                        <td>
                            {{ $user->name }}
                        </td>
                        <td>
                            <a wire:click="$emit('showModal')">Edit</a>
                        </td>
                   </tr>

                @endforeach

                @livewire('user-modal', $user)

This kinda works and the modal opens however I get the following error in my console when I open the modal, I have tried specifying the wire:id as well as a key.

I tried adding the following on the table row as the troubleshooting docs but it seemed to break it.

wire:key="{{ $loop->index }}"

Code for the modal:

    public $user;
public $isOpen = false;

protected $listeners = [
    'closeModal',
    'showModal' => 'open',
];

public function open()
{
    $this->isOpen = true;
}

public function close()
{
    $this->isOpen = false;
}

public function mount(User $user)
{
    $this->user = $user;
}

public function render()
{
    return view('livewire.user-modal', [
        'user' => $this->user
    ]);
}

The blade file:

<div class="modal {{ $isOpen ? 'd-block' : '' }}">
<div class="modal-dialog" role="document">
    <div class="modal-content">
        <div class="modal-header">
            <h5 class="modal-title">{{ $user->name }}</h5>
            <button class="close" wire:click="$emit('close')">
                <span>&times;</span>
            </button>
        </div>
     </div>
  </div>
 </div>

Any ideas?

Hey @jethromay.

I’m not 100% on this, but I think you need to wrap the modal view file with another div. Livewire attaches itself to the first div in the view, and I think having livewire changing the class here:
<div class="modal {{ $isOpen ? 'd-block' : '' }}">
which is the same div livewire is going to attach an id to, is what’s causing a problem.

The reason I’m not 100% is because the error is referencing an area of your code that has a text input with the expiry_date name and id which you don’t have posted here. If that doesn’t solve the issue, we will need the full contents of the blade file that contains your table and/or where that input is.

Based solely on the code you do have posted, I did notice is that your modal component is outside of the foreach statement running through the users. I believe the reason you aren’t getting an error passing in the $user variable outside of the loop is that php will still let you access the $user variable from the last time iteration. You have 2 fixes. You can move the component into the loop and add an index key, and that component will be recreated for each user.

@livewire('user-modal', $user, key($index->loop))

It’s also completely fine to only have the component registered once outside of the loop, you just have to tell the modal component which user to load, which can be done with the event.

Change the event trigger to pass the user id:
<a wire:click="$emit('showModal', {{ $user->id}})">Edit</a>

And make use of it in your component’s open() method:

public function open($userId)
{
    $this->isOpen = true;
    $this->user = User::find($userId)
}

Each way has it’s ups and downs. My personal rule of thumb is will use the first way until there are more than 20, then I will switch to the second.

i think its because of

Can you try removing id Property in DOM