I'm trying to create a way to dynamically load Livewire nested components by having a main container component like this:
ComponentContainer.php
class ComponentContainer extends Component
{
public $component = 'active';
protected $listeners = [
'switch'
];
public function switch(string $component)
{
$this->component = $component;
}
public function render()
{
return view('livewire.component-container', [
'component' => $this->component,
'key' => random_int(PHP_INT_MIN, PHP_INT_MAX),
]);
}
}
component-container.blade.php
<div>
<h1>Component Container</h1>
@livewire($component, key($key))
<button wire:click="$emit('switch', 'active')">
{{ __('Active') }}
</button>
<button wire:click="$emit('switch', 'expired')">
{{ __('Expired') }}
</button>
</div>
It's working insomuch as when I click "active" or "expired" it's loading one of these components:
Active.php
class Active extends Component
{
public function render()
{
return view('livewire.active');
}
}
active.blade.php
<div>
active
</div>
Expired.php
class Expired extends Component
{
public function render()
{
return view('livewire.expired');
}
}
expired.blade.php
<div>
expired
</div>
But I get the following error in the console log, and I don't understand why:
Livewire: Multiple root elements detected. This is not supported. See docs for more information https://laravel-livewire.com/docs/2.x/troubleshooting#root-element-issues <div wire:id="jdHgW7KzB3wWUCl7vMI4">expired
Doesn't seem to make sense as it's clearly just one root element. Interestingly it doesn't do it on the first load, regardless of whether I set $component to active or expired
wire:endHTML comment being missing. I eventually discovered that it was only happening when the dynamic component call was placed above the buttons that emit the event. I've added an answer accordingly.