Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

valentin_vranic's avatar

#[Modelable] not working with wire:show/x-show

For some reason #[Modelable] does not work on conditionally shown elements.

<div class="col-md-4 text-end" wire:show="form.isAuthorizedVisible">
    <select id="manivox_numbers" wire:model="form.numbers" class="form-select" multiple></select>
    <livewire:manage-cli wire:model="form.numbers" lazy/>
</div>

So, doesn't work like this. But when I remove the wire:show part it will work, and run into manage-cli components mount method, and bind to the property.

#[Modelable]
public $numbers;

Have no clue why does it works like this?

Any idea?

0 likes
4 replies
LaryAI's avatar
Level 58

The issue you're encountering is related to the use of wire:show and x-show in Livewire. These directives are not native to Livewire and are likely being confused with Alpine.js's x-show. Livewire does not have a wire:show directive, which means that the conditional rendering logic you're trying to apply won't work as expected.

Here's a solution to achieve the desired behavior using Livewire's native features:

  1. Use wire:if or wire:key for Conditional Rendering:

    Instead of using wire:show, you can conditionally render the component using @if in Blade or wire:key to ensure the component is re-rendered when the condition changes.

  2. Use Alpine.js for Conditional Display:

    If you want to conditionally show/hide elements on the client side without re-rendering, you can use Alpine.js's x-show directive. Ensure Alpine.js is included in your project.

Here's how you can modify your code:

<div class="col-md-4 text-end" x-data="{ isAuthorizedVisible: @entangle('form.isAuthorizedVisible') }">
    <div x-show="isAuthorizedVisible">
        <select id="manivox_numbers" wire:model="form.numbers" class="form-select" multiple></select>
        <select id="manivox_numbers_ds" class="form-select" style="display: none;"></select>
        <livewire:manage-cli wire:model="form.numbers" lazy/>
    </div>
</div>

Explanation:

  • x-data and x-show: This uses Alpine.js to manage the visibility of the element. The x-data directive initializes a local Alpine.js component state, and x-show conditionally displays the element based on the isAuthorizedVisible property.

  • @entangle: This directive is used to bind Livewire properties to Alpine.js, allowing them to stay in sync.

By using Alpine.js for the client-side visibility and Livewire for server-side data binding, you can achieve the desired behavior without running into issues with non-existent Livewire directives. Make sure Alpine.js is included in your project for this to work.

vincent15000's avatar

Can you show the code for the manage-cli component please ? Controller and view ...

valentin_vranic's avatar

@vincent15000 in meantime I've figured out, that I was using modelable two times. Because inside of manage-cli there is a dialog, which uses modelable too.

However, I've encountered now another issue, after rewriting the logic for the dialog.

I'll copy/paste my question from livewire discord chat

Hi all! I'm trying to use #[Modelable] and I'm curios how to use it for select, or my scenario

So my approach is to open up a dialog (livewire component), there select couple of things, and when close the dialog then to update select options in parent blade.

Well, bcs I don't want to re-render, the modal after property update, I dispatch an event on each select change event and update the property, which is binded to the parent. However it's not working..

$wire.dispatch('setNumbers', [selectedValues]);

    #[Modelable]
    public $numbers;

    #[Renderless]
    #[On('setNumbers')]
    public function setNumbers(array $numbers): void
    {
        $this->numbers = $numbers;
    }

And in my parent view, it looks like this

<div class="col-md-4 text-end" wire:show="form.isAuthorizedVisible">
    <select id="numbers" class="form-select mb-2">
        @foreach($form->numbers as $number)
            <option value="{{$number}}">{{ $number }}</option>
        @endforeach
    </select>
    <livewire:manage-cli wire:model="form.numbers"/>
</div>
1 like

Please or to participate in this conversation.