I was not sure wether this belongs on the Alpine or Livewire repository. If this is not the right place I will happily move it over.
I have been building a comment section using Alpine and Livewire and am really impressed. There is just one challenge which has been keeping me busy for 2 days now. Users should be able to edit comments using a modal. However, the modal disappeared the moment Livewire processed the input.

After hours trying to get to the core of the problem this is where I left.
<div x-data="{}">
<div x-data="{show: false}">
<button @click="show = true">Show input</button>
<input x-show="show" x-cloak type="text" wire:model="value">
</div>
</div>

In this example, I expect the input element to persist which is the case when you remove the nesting or the x-cloak attribute. It would be great if anyone sees a connection. I am really curious to understand what's going on.
Looking at it at first sight, can you try to not use @click on button. Instead use x-on:click since both livewire and Alpine uses same directive for click event. That might be the issue. Let's see how it goes. And why there is x-cloak?
<div x-data="{show: false}">
<button x-on:click="show = true">Show input</button>
<input x-show="show" type="text" wire:model="value">
</div>
Thanks! I tried it but it did not change the behavior. The example is over-simplified. The input element in a real app would be wrapped inside a modal. Without x-cloak the modal flickers before Alpine loads.
maybe you should have a look at this. Sounds like related to debounce
or Lazily Updating
<input type="text" wire:model.lazy="value">
I think it's a Livewire bug (I believe the Alpine integration lives in that repository).
If you try this snippet
<div x-data="{}">
<div x-data="{show: false}">
<button @click="show = true">Show input</button>
<span x-text="show"></span>
<input x-show="show" type="text" wire:model="value">
</div>
</div>
You can see that show gets reverted to false every time Livewire refreshes the Livewire component but it works correctly if your Alpine component is not nested.
I don't think x-cloak makes much difference here.
Okay, it turned up that it might be more complicate than that.
Livewire, when updating its component, walks the old dom and clones the old Alpine components into the new ones.
The clone function in Alpine does
clone: function clone(component, newEl) {
if (!newEl.__x) {
newEl.__x = new Component(newEl, component.getUnobservedData());
}
},
In that snippet. Livewire knows that he need to clone
This happens sequentially and it does the parent first: when Alpine initialises the parent, because it finds a x-data in one of their children, it also initialise the nested component using the original data in your html then it tries to clone the child component but, because the component has already been initialised, it skips this phase.
Changing clone to
clone: function clone(component, newEl) {
newEl.__x = new Component(newEl, component.getUnobservedData());
},
seems to fix the issue but I'm not familiar with the integration so I don't know if it would break something else.
cc. @calebporzio
Thanks for diving into this! You are right. x-cloak does not make a difference because now there is a x-text. If you remove x-text the snippet starts working as expected again. Just figured out that this is also the case for other directives like x-htmland x-bind.
I might be missing something here, but do you not just need to add wire:ignore to your element that keeps getting overwritten by livewire?
I might be missing something here, but do you not just need to add
wire:ignoreto your element that keeps getting overwritten by livewire?
Then you wouldn't be able to use wire:model="value" in the example above. My use case is also similar.
Wouldn't wire:ignore.self work?
Wouldn't
wire:ignore.selfwork?
Not for me because it's the same element. A datepicker in a modal.
I've got the same issue with x-cloak and livewire component.
Without x-cloak eveything works well, but I need it to prehide elements.
gif
button:
```
<a href="#!" class="btn-search btn" uk-tooltip="title: Znajd藕 restauracj臋; pos: right"
x-on:click.prevent="open=true
$nextTick(() => $refs.fullSearchInput.focus())">
<i class="gg-search-loading"></i></a>
@livewire('left-menu')
</li>
Component ('left-menu')
```
Any solution to prehide elements?
I have the same behaviour with Phoenix LiveView. It's not related to x-cloak for me.
What @SimoTod suggested actually works for me.
@ssbb can you post a snippet for LiveView? 馃檹
@RxAssim I am just forked Alpine repo and did this changes.
Most helpful comment
I think it's a Livewire bug (I believe the Alpine integration lives in that repository).
If you try this snippet
You can see that
showgets reverted tofalseevery time Livewire refreshes the Livewire component but it works correctly if your Alpine component is not nested.I don't think x-cloak makes much difference here.