I’ve got an interesting one for all you LiveView peeps out there. I’m not 100% sure of my analysis, but allow me to paint a picture before I get to my question.
The system I am building is essentially a workflow-specific Kanban board with task cards arranged in a grid.
The kanban board is a LiveView. Clicking a card uses live_patch
to open it in a modal dialog as a LiveComponent. On the card is a form with a phx-change
event used for both validation and auto-recovery purposes. This question is going to be about auto-recover.
On page load of the LiveView (Kanban board), Phoenix gives the LV an ID, e.g. phx-Fn1s7NJqKqkaDAGB
. When the first LiveComponent (the modal) is rendered, it gets an id too: phx-Fn1s7NJqKqkaDAGB-1-0
, and so does the nested LiveComponent (the card): phx-Fn1s7NJqKqkaDAGB-2-0
. As you can see, each LiveComponent gets the parent LV ID and an incremented suffix.
To test data recovery, I have exposed the LiveView socket on the Window object as ls
, and can use ls.disconnect()
and ls.connect()
in the browser’s console to simulate a network drop. When I enter form data in the nested component, disconnect, and reconnect, the form data is recovered and everything’s grand. This works, because the newly generated live components have the same IDs as their already existing client side counterparts, i.e. phx-Fn1s7NJqKqkaDAGB-1-0
& phx-Fn1s7NJqKqkaDAGB-2-0
.
However, when I close the modal normally (live_patch
back to the LiveView URL), destroying the live components, and click on another card (or the same card, doesn’t matter), the live components get new IDs; the modal gets phx-Fn1s7NJqKqkaDAGB-3.0
and the card gets phx-Fn1s7NJqKqkaDAGB-4.0
. Repeating this generates IDs 5 and 6, then 7 and 8, and so on.
No problem really, except that now when I drop and restore the network, after the LiveView gets re-rendered all unsaved data is lost. This is because the component ID suffixes are regenerated from 1 after the mount (as before), but their client side counterparts are not suffixed 1-0 and 2-0 as they were the first time, they are instead numbered, for instance, 7-0 and 8-0. Consequently, these client-side components from before the disconnect get destroyed and auto-recovery is not attempted.
To restate, if a LV component is removed from the DOM and added again, form auto-recovery will not work. Or so it appears.
Now, I don’t think anyone—even me—would call this a bug, but I was wondering if anybody had any thoughts on this behavior or, ideally, any workarounds. I suppose I could write an Amnesia-backed phx-auto-recover
event or some such, but that seems like overkill for a simple form. I’m willing to do it, but I am hoping for some additional insight first. Maybe a client-side solution would be better? Maybe my analysis is all wrong? Any thoughts?