JGonsuron's avatar

Passing data to a modal

I am working on a project where in the right column a list of current users is lopped through and displayed. When the User's name is clicked, a modal is triggered and pops up so the current user can follow that person. The issue I am having is that the info displayed in the modal reflects only the last user registered in the database instead of the user clicked. How can I pass the information correctly to the modal?

Blade File

<div>
    <h3 class="font-bold text-xl mb-4">Active Users</h3>

    <ul>
        @foreach ($users as $user)
            @if ($user->role === "agent")
                <li class="mb-4">
                    <div class="flex items-center text-sm">
                        <img src="{{ $user->profile_photo_url }}" alt="{{ $user->name }}'s Profile picture" class="rounded-full h-10 w-10 object-cover mr-2">

                        <div wire:click="showModal" :users="$user" :key="$user" class="cursor-pointer">
                            {{ $user->name }} 
                        </div>
                        
                    </div>
                </li>
            @endif
        @endforeach
    </ul>

    <x-jet-dialog-modal wire:model="modalFormVisable">
        <x-slot name="title">
            {{ $user->name }}
        </x-slot>

        <x-slot name="content">
            
            <div class="mt-4">
                <img src="{{ $user->profile_photo_url }}" alt="{{ $user->name }}'s Profile picture" class="rounded-full h-10 w-10 object-cover mr-2">
                
            </div>
                        
            
        </x-slot>

            <x-slot name="footer">
                <x-jet-button class="ml-2" type="submit" wire:loading.attr="disabled">
                    {{ __('Follow Me') }}
                </x-jet-button>
        </x-slot>
    </x-jet-dialog-modal>
</div>

Livewire Controller

<?php

namespace App\Http\Livewire;

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

class Users extends Component
{

    public $users;
    public $modalFormVisable = false;
    
    

    public function showModal() 
    {
        $this->modalFormVisable = true;
    }

    public function mount()
    {
        $this->users = User::where('id', '!=', auth()->id())->get();
    }

    public function render()
    {
        return view('livewire.users');
    }
}
0 likes
14 replies
MarianoMoreyra's avatar

Hi @jgonsuron

I’d add a public $selectedUser to your component do you can then pass the corresponding user to the showModal method:

< div wire:click="showModal($user)" :users="$user" :key="$user" class="cursor-pointer">
                            {{ $user->name }} 
                        </div>

Then at the showModal method:

    public function showModal($user) 
    {
        $this->selectedUser = $user;
        $this->modalFormVisable = true;
    }

And finally you reference the selectedUser at your modal:

     <x-jet-dialog-modal wire:model="modalFormVisable">
        <x-slot name="title">
            {{ $selectedUser->name }}
        </x-slot>

        <x-slot name="content">
            
            <div class="mt-4">
                <img src="{{ $selectedUser->profile_photo_url }}" alt="{{ $selectedUser->name }}'s Profile picture" class="rounded-full h-10 w-10 object-cover mr-2">
                
            </div>
                        
            
        </x-slot>

Hope this works!!

You’ll probably have to do some adjustsments tho, as I’m writing this from my phone so I’m sure there must be some typos

JGonsuron's avatar

Thanks for the reply. I tried this out and then got the Trying to get property 'name' of non-object error. I looked at a few examples on StackOverflow and tried a few solutions with no success.

MarianoMoreyra's avatar

@jgonsuron

I see...you have to either initialize the variable (new User) or check for nulls at the modal:

<x-jet-dialog-modal wire:model="modalFormVisable">
        <x-slot name="title">
            {{ $selectedUser->name ?? '' }}
        </x-slot>

        <x-slot name="content">
            
            <div class="mt-4">
                <img src="{{ $selectedUser->profile_photo_url ?? '' }}" alt="{{ $selectedUser->name ?? '' }}'s Profile picture" class="rounded-full h-10 w-10 object-cover mr-2">
                
            </div>
                        
            
        </x-slot>

Hope it works now!

JGonsuron's avatar

The modal comes up without the error, but the name doesn't come in. Sorry, I have been trying for several weeks to make this work. I usually give up for a few days and work on another feature, but I am being held up at this point by this issue.

JGonsuron's avatar

Here is the Component Blade

<div>
    <h3 class="font-bold text-xl mb-4">Active Users</h3>

    <ul>
        @foreach ($users as $user)
            @if ($user->role === "agent")
                <li class="mb-4">
                    <div class="flex items-center text-sm">
                        <img src="{{ $user->profile_photo_url }}" alt="{{ $user->name }}'s Profile picture" class="rounded-full h-10 w-10 object-cover mr-2">

                        <div wire:click="showModal" :users="$user" :key="$user" class="cursor-pointer">
                            {{ $user->name }} 
                        </div>
                        
                    </div>
                </li>
            @endif
        @endforeach
    </ul>

    <x-jet-dialog-modal wire:model="modalFormVisable">
        <x-slot name="title">
            {{ $selectedUser->name ?? '' }}
        </x-slot>

        <x-slot name="content">
            
            <div class="mt-4">
                <img src="{{ $user->profile_photo_url }}" alt="{{ $user->name }}'s Profile picture" class="rounded-full h-10 w-10 object-cover mr-2">  
            </div>
                        
            
        </x-slot>

            <x-slot name="footer">
                <x-jet-button class="ml-2" type="submit" wire:loading.attr="disabled">
                    {{ __('Follow Me') }}
                </x-jet-button>
        </x-slot>
    </x-jet-dialog-modal>
</div>

Here is the Livewire Controller

<?php

namespace App\Http\Livewire;

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

class Users extends Component
{

    public $users;
    public $modalFormVisable = false;
    public $selectedUser;


    public function showModal(User $user) 
    {
        $this->selectedUser = $user;
        $this->modalFormVisable = true;
    }

    public function mount()
    {
        $this->users = User::where('id', '!=', auth()->id())->get();
    }

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

As you can see, I added Type hinting to the showModal method. When just the $user variable is in, I get this error:

Illuminate\Contracts\Container\BindingResolutionException
Unable to resolve dependency [Parameter #0 [ <required> $user ]] in class App\Http\Livewire\Users
MarianoMoreyra's avatar

@jgonsuron you’ve missed the first part of my original post.

You have to pass the corresponding user at the click event:

<div wire:click="showModal($user)" :users="$user" :key="$user" class="cursor-pointer">
                            {{ $user->name }} 
                        </div>

If it doesn’t work with the added type hint, try removing it after adding the parameter to the click call

JGonsuron's avatar

I did it exactly as you outlined. Now the modal doesn't even pop up. Edit: I didn't change the blade directive.

<x-slot name="title">
            {{ $selectedUser->name }}
        </x-slot>

When I do it like this, I get this:

ErrorException
Trying to get property 'name' of non-object (View: C:\Users\User\Code\realtor\resources\views\livewire\users.blade.php)
http://127.0.0.1:8000/dashboard
JGonsuron's avatar

When I do this:

<x-slot name="title">
            {{ $selectedUser->name ?? ''}}
        </x-slot>

The modal doesn't pop up.

MarianoMoreyra's avatar
Level 25

I'm sorry @jgonsuron

You probably already solved this. But just in case you haven't, try this at the blade:

<div wire:click="showModal({{$user->id}})" :users="$user" :key="$user" class="cursor-pointer">
                            {{ $user->name }} 
                        </div>

I forgot that this is the way to pass the parameters in Livewire:

ref: https://laravel-livewire.com/docs/2.x/actions#action-parameters

And then at the Component, type hint the User as you already did before:

    public function showModal(User $user) 
    {
        $this->selectedUser = $user;
        $this->modalFormVisable = true;
    }

Finally, at the Modal, this is the way it should work now the event parameter is passed as supposed:

<x-slot name="title">
            {{ $selectedUser->name ?? ''}}
        </x-slot>
1 like
JGonsuron's avatar

I tried this solution. Still doesn't work. I am just going to ditch Livewire and implement another solution. As much as I wanted a modal for this feature, I just don't think it is possible using Livewire. I do appreciate your help.

MarianoMoreyra's avatar

That's weird @jgonsuron

I've just reproduce this locally as suggested in my last reply and it's working for me! So just to be sure...you tried changing the showModal call to pass the id like this?

showModal( {{$user->id}} )

with the curly braces around the $user->id?

Anyway, I understand your frustration, although you may encounter similar problems with Vue and Inertia, or even with vanilla JavaScript, since sometimes there is a little detail that we are missing.

Hope you get to make this work with whatever you choose to work with!

JGonsuron's avatar

Happy to let you know that it is now working! I had forgotten to declare the $selectedUser variable in the controller, so it was a pretty stupid oversight on my part. Thanks again for taking the time to help me with this.

Please or to participate in this conversation.