I have a button...
<button wire:click="$emitTo('components.modals.player-modal', 'showModal', '{{ $player->id }}')" class="focus:outline-none"> {{ $player->first_name . ' ' . $player->last_name }} </button>
...That triggers a modal similar to the Code Course tutorial: Global Modals with Livewire and Alpine.js. Where a "PlayerModal" livewire controller extends a "Modal" livewire controller...
namespace App\Http\Livewire\Components\Modals;
use Livewire\Component;
use App\Models\Player;
class Modal extends Component
{
public $showModal = false;
public Player $player;
public $listeners = [
'showModal' => 'showModal',
];
public function showModal(Player $player)
{
$this->showModal = true;
$this->player = $player;
}
}
namespace App\Http\Livewire\Components\Modals;
use Livewire\Component;
use App\Http\Livewire\Components\Modals\Modal;
use App\Models\Player;
class PlayerModal extends Modal
{
public $playerModalShow = 'playerEdit'; // default view
public Player $player;
public $listeners = [
'playerModalNavClicked' => 'changePlayerView'
];
public function mount(Player $player)
{
$this->player = $player;
}
public function changePlayerView($value)
{
$this->playerModalShow = $value;
}
public function render()
{
return view('livewire.components.modals.player-modal');
}
}
...In the blade of the PlayerModal, I have 3 child livewire components:
<div class="grid sm:grid-cols-1 md:grid-cols-4 gap-3 mt-6">
<button wire:click="changePlayerView('playerEdit')" class="text-white bg-accent hover:scale-105 hover:brightness-150 shadow-lg font-medium rounded-lg text-lg px-5 py-2.5 text-center mb-2 transition duration-300 {{ $playerModalShow == 'playerEdit' ? 'active-nav' : '' }}">Edit Player</button>
<button wire:click="changePlayerView('playerActions')" class="text-white bg-accent hover:scale-105 hover:brightness-150 shadow-lg font-medium rounded-lg text-lg px-5 py-2.5 text-center mb-2 transition duration-300 {{ $playerModalShow == 'playerActions' ? 'active-nav' : '' }}">Actions</button>
<button wire:click="changePlayerView('playerStats')" class="text-white bg-accent hover:scale-105 hover:brightness-150 shadow-lg font-medium rounded-lg text-lg px-5 py-2.5 text-center mb-2 transition duration-300 {{ $playerModalShow == 'playerStats' ? 'active-nav' : '' }}">Stats & Contracts</button>
<button wire:click="changePlayerView('playerRatings')" class="text-white bg-accent hover:scale-105 hover:brightness-150 shadow-lg font-medium rounded-lg text-lg px-5 py-2.5 text-center mb-2 transition duration-300 {{ $playerModalShow == 'playerRatings' ? 'active-nav' : '' }}">Ratings</button>
</div>
namespace App\Http\Livewire\Components\Modals;
use Livewire\Component;
use App\Models\Player;
class PlayerModalNav extends Component
{
public $playerModalShow;
public function changePlayerView($value)
{
$this->playerModalShow = $value;
$this->emit('playerModalNavClicked', $value);
}
public function render()
{
return view('livewire.components.modals.player-modal-nav');
}
}
My issue now is when I add the $listeners on the Player Modal livewire controller (PlayerModal.php), the button that triggers the modal stops working.
Any assistance would be greatly appreciated!
Hello,
It looks like your emitTo
is wrong.
Quote from the Livewire documentation:
Sometimes you may only want to emit an event to other components of the same type.
In these cases, you can use emitTo:
https://laravel-livewire.com/docs/2.x/events#scope-by-name
It doesn't look like playerModalNavClicked
is a component. Try player-modal
(PlayerModal) instead.
I have 3 child livewire components
Make sure they are correctly nested.
You could also just use emit
instead of emitTo
just to get it working initially, and then refactor.
Ahh yes, I had "emit" only initially and was trying some different things--forgot to change it back. But still no success. When the $listeners are added on the PlayerModal.php, the button click no longer opens the modal.
What do you mean by correctly nesting the components?
the button click no longer opens the modal
Are you getting any errors?
What do you mean by correctly nesting the components?
I mean, double check they are nested in the component view. but I guess this doesn't matter if you are using emit
.
Can you share more code? Could you share all of the components and views perhaps?
No errors...just pointer cursor with no action on click.
And yes, happy to share everything. I should also mention, I have this exact navigation system working in another part of the app. I have everything exactly like I have it there but that modal button just stops working when the $listeners are added on PlayerModal.php.
<div>
<x-modals.modal-base wire:model="showModal">
<div class="relative w-full max-h-full shadow-md p-4 bg-light0 dark:bg-dark0 text-light5 dark:text-dark5">
<div>
<!-- Modal content -->
<div class="px-6 pb-6">
<!-- CONTENT HERE -->
<!-- MODAL NAV -->
@livewire('components.modals.player-modal-nav', ['playerModalShow' => $playerModalShow])
</div>
<!-- Show content based on nav -->
<div>
@if ($playerModalShow == 'playerEdit')
@livewire('components.modals.player-edit')
@elseif ($playerModalShow == 'playerRatings')
@livewire('components.modals.player-ratings')
@endif
</div>
</div>
</div>
</x-modals.modal-base>
</div>
<div
x-data="{showModal: @entangle($attributes->wire('model')).defer}"
x-show="showModal"
x-on:keydown.escape.window="showModal = false"
class="fixed top-0 left-0 right-0 z-50 p-4 overflow-x-hidden overflow-y-auto md:inset-0 h-[calc(100%-1rem)] max-h-full"
>
<div x-show="showModal" class="fixed inset-0 transform" x-on:click="showModal = false">
<div class="absolute inset-0 bg-light5 opacity-80"></div>
</div>
<div x-show="showModal" class="top-10 border border-4 dark:border-dark2 shadow-2xl relative w-full max-w-4xl max-h-full rounded-lg overflow-hidden transform w-full mx-auto">
{{ $slot }}
</div>
</div>
<button wire:click="$emitTo('components.modals.player-modal', 'showModal', '{{ $player->id }}')" class="focus:outline-none">
{{ $player->first_name . ' ' . $player->last_name }}
</button>
I believe that's everything relevant to the modal and nav.
Hi,
<button wire:click="$emitTo('components.modals.player-modal', 'showModal', '{{ $player->id }}')" class="focus:outline-none">
{{ $player->first_name . ' ' . $player->last_name }}
</button>
Where is this exactly? The issue you are describing sounds very odd. Mind sharing the repo so I can take a closer look for you?
I think if I was to try to re-create the issue with the provided code, I don't think I would encounter the issue, but I am sure there are many other parts that can factor to the behaviour you are seeing.
That button is on "franchise-rosters.blade.php" page.
I'm having trouble getting the repository on github. So I've just zipped the directories and put them in a Google Drive link. Hope that's ok.
https://drive.google.com/file/d/1A7uIMR8QGO9Av_oDHZq9EBuAlmH9S2AH/view?usp=sharing
I appreciate your help on this.
Yes, that's fine. Looking into it now. Will update this post soon.
@alexjolley Going to need some information from you. How can I clearly reproduce the issue?
I have imported the default_values.sql
into the database. I have tried creating a franchise, but it simply redirects back and fails to create the resource. Even after manually creating the records in the database, I am still not seeing a simple path to the issue.
I am also getting some security warnings when running npm run dev
. What's with that?
Ahh yes, importing those default_values.sql should get the DB to a working point. Then the team rosters need to be imported to the DB by going to the "Import Roster" page in the app, naming it and clicking "Import Existing JSON File." This will import a json file from inside storage/madden_data/maddenexporter_json/rosters to the DB. Then you can return to the "Home" page and click the "New Franchise" button. You can select any roster type and team and it will generate a new franchise. On the "rosters" tab, the goal is to click on a player's name and the modal will open to show more details about the player. This is where the problem occurs and when the $listeners are added on the PlayerModal.php that button on the player name stops opening the modal.
Not sure what that security warning is about...I'm not getting that. Maybe once the roster file is imported that will be fixed?
Thanks
@alexjolley It seems you are overriding the listeners defined in Modal.php
.
Removing this from PlayerModal.php
:
public $listeners = [
'playerModalNavClicked' => 'changePlayerView'
];
Adding this to Modal.php
:
class Modal extends Component
{
public $showModal = false;
public Player $player;
public $listeners = [
'showModal' => 'showModal',
];
public function showModal(Player $player)
{
dd('hello');
$this->showModal = true;
$this->player = $player;
}
}
I see the dd
after clicking the button. The modal doesn't appear to show, but that's another issue entirely. I'll leave you to debug that.
If you want to keep the original listener, make sure to add showModal
there too.
public $listeners = [
'showModal',
'playerModalNavClicked' => 'changePlayerView',
];
You are also defining $player
twice too.
Edit: If you move the Livewire component to the top, the modal shows, though the styling is a bit borked.
Move from:
</div>
@livewire('components.modals.player-modal')
</div>
Move to:
<div>
@livewire('components.modals.player-modal')
<!-- HEADER -->
I hope this helps! :)
You're a life-saver, thank you!! I should've realized that but I really appreciate a second pair of eyes.
@alexjolley No worries. Don’t forget to mark a best answer if solved. :)