You could wrap your Livewire component inside another Livewire component, that renders the child component when the button is clicked.
Render Component on Button Click
Hi, was wondering whether its possible to render a Livewire component on the click of a button? I need a way of specifying where the component should render on the page, and then have it render once a button is clicked. Trying to change the content of a slide over menu dependent on a radio button selection, and currently using "display: none;"/"hidden" and then JavaScript to do so. Wanting to look into the possibility of Livewire components so they're not loaded until the specific button is clicked. Thanks in advance.
How exactly would I go about doing that? I've read a little about firing events and event listeners, though wasn't able to fully wrap my head around it.
Just as you normally would. As a minimal example:
View file of your "parent" component
<div>
<button wire:click="showButton">
Show other button
</button>
@if($buttonVisible)
<livewire:your-button-component />
@endif
</div>
Inside your parent component
public function showButton()
{
$this->buttonVisible = true;
}
If it doesn't make sense in your case to wrap one component into another and as long as the components are on the same page you can make use of events/listeners as you already pointed out.
Thanks, this has helped a lot. However, in your example you placed the button inside the parent component, does the button have to be in the component of can it just be in the page's blade file that the component is on?
As mentioned you can have two separate Livewire components that are on the same page and communicate via events. For example:
Component 1
public function showButton()
{
$this->emit('showButton');
}
Component 2
public bool $buttonVisible = false;
protected $listeners = ['showButton'];
public function showButton()
{
$this->buttonVisible = true;
}
This is on my button's component:
<?php
namespace App\Http\Livewire;
use Livewire\Component;
class BttnTest extends Component
{
public bool $buttonVisible = false;
protected $listeners = ['showButton'];
public function showButton()
{
$this->buttonVisible = true;
}
public function render()
{
return view('livewire.bttn-test');
}
}
This on my content's component:
<?php
namespace App\Http\Livewire;
use Livewire\Component;
class ContentTest extends Component
{
public function showButton()
{
$this->emit('showButton');
}
public function render()
{
return view('livewire.content-test');
}
}
Then this is how I've got it setup on my page:
<body>
<livewire:bttn-test/>
@if($buttonVisible)
<livewire:content-test/>
@endif
@livewireScripts
</body>
It tells me that the "buttonVisible" variable isn't defined, is it because the functions and variable is within the class? I'm clueless honestly, never used these before so I appreciate your help.
Your "buttonVisible" property is part of your BttnTest component, so it's only available inside its view. So you should add it to the view
<div>
@if($buttonVisible)
<button>...</button>
@endif
</div>
and not to the page containing the view/component.
Would that not make it so the button is invisible? I'm wanting the content to be invisible until I've pressed the button.
You said that you want a button to appear when another button is clicked. You can apply that to whatever you want to be visible when the button is clicked.
Sorry, I must've said button by mistake. Either way got it working on the content now, but it's quite slow and takes a few seconds for it to render. Is this something we'd be able to speed up or is there no way around it?
Depends what your content looks like. Do you have to query the database in order to get the content? In the end Livewire is making requests to the server, which result in a small delay. If it makes sense in your case you can use wire:click.prefetch in order to speed it up.
What if we have to load on click just one nested component inside a loop? I've already implemented events but I don't know how to render the component
Please or to participate in this conversation.