Live_redirect and alpinejs

I have a drawer animated with alpinejs on several live view pages, the drawer is different on each live view page. it opens or closes on a click with a simple
@click=“menu_open = !menu_open”

everything is ok on a full page refresh

but if I live_redirect instead of link from one live view to the other, the drawer on the landing page is frozen

with live view 0.17.2 and alpinejs 3

PS I have the onBeforeElUpdated callback setup as required for alpinejs.

the drawer is well there after live_redirect and if I manually set its x-show attribute to true it shows
but the menu_open=!menu_open action triggered from a simple button seems frozen

moreover I can trigger the drawer using the alplinejs firefox debug tab for instance
but clicking on the button which is normally used for that on the page does nothing, only I see the page gutters appearing and disappearing (it is a large drawer) but no drawer

investigating further, using a watch

div id={@id} x-data=“{menu_open: false}” x-init=“$watch(‘menu_open’, value => console.log(‘menu_open:’ +value))”>
<button type=“button” @click=“menu_open = !menu_open” >toggle
/div>

it appears that on click the menu_open variable rapidly takes values
menu_open:true
menu_open:false

as if there were two toggle instructions on click, so it appears on live_redirect the call back in x-data is added to a previous one that existed on the page before the live_redirect

Have you considered using the global store provided with Alpine 3?

not yet but isn’t it adding too much complexity for simple button and drawer with no dependency ?

We’re having similar problems with Alpine 3 where alpine seems to not update its internal state correctly. We can see that it initializes several times with x-init. Logging what our scope in x-data show everything to be fine, but then when alpine is rendering it is not consistent.

One workaround that we are using to be able to progress is to add a hook and initialize the data separately from x-data on mount.

Hooks.MultiSelectInput = {
  mounted() {
    let event = new CustomEvent("init-data", {});
    setTimeout(() => {
      this.el.dispatchEvent(event);
    }, 100);
  }
}

And then on our component we use something like this.

    <div 
      phx-hook="MultiSelectInput" 
      x-on:init-data="initData();"
      x-data={"{
              __selected: [],
              __options: [],
              initData() {
                this.__selected = #{Jason.encode!(@selected_options)};
                this.__options = #{Jason.encode!(@options)};
              }
      }"}

where __options is an simple array which we render in and x-for.

Without this delayed initialization of the data, our x-for will run more that times than there are elements in __options, creating some strange behaviors.

I wish I had more time to debug and try to reproduce in a minimal project, but that will take a while.

Thanks for the workaround with alpinejs,
another workaround without it, for simple things, is to rely on LiveView.JS new functions