ammancilla

ammancilla

LiveView form auto-recovery not working when form is rendered through a Live Component

TLDR; A recoverable form rendered through a Live Component doesn’t recover after crashes or disconnects.


DETAILS

Specifications

  • Phoenix 1.7.14
  • LiveView 0.20.17 && 1.0.0-rc.7

Context
A form is being rendered through a Live Component. It fulfills the requirements to be recoverable after crashes and disconnects, as per Form bindings — Phoenix LiveView v1.2.5

  • Has an ID.
  • Is marked with phx-change.

all forms marked with phx-change and having id attribute will recover input values automatically after the user has reconnected or the LiveView has remounted after a crash.

Expected Behaviour

  • After the live view crashes or disconnects, the form rendered through the Live Component is recovered.

Current Behavious

  • After the live view crashes or disconnects, the from rendered through the Live Component is not recovered.
on Crash on Disconnect
ezgif-5-f640ca9302 ezgif-5-77f2b21c91

Steps to reproduce

  1. Clone https://github.com/ammancilla/phoenix_live_view_unrecoverable_form
  2. mix phx.server
  3. http://localhost:4000/form

or

  • The Live View and respective Live Component
defmodule FormRecoverableWeb.FormLive do
  @moduledoc false

  use FormRecoverableWeb, :live_view

  @impl true
  def mount(_params, _session, socket) do
    {:ok, assign(socket, :form, to_form(%{"name" => nil}))}
  end

  @impl true
  def handle_event("validate", params, socket) do
    {:noreply, assign(socket, :form, to_form(params))}
  end

  def handle_event("submit", _params, socket), do: raise("break live view")

  @impl true
  def render(assigns) do
    ~H"""
    <div class="mx-auto flex justify-between prose">
      <div>
        <h2>The Form</h2>
        <.simple_form id="person-form" for={@form} phx-change="validate" phx-submit="submit">
          <.input field={@form[:name]} label="name" />
          <:actions>
            <.button phx-disable-with="Saving...">Crash LiveView</.button>
          </:actions>
        </.simple_form>
      </div>

      <div>
        <h2>The Form from a Live Component</h2>
        <.live_component
          id="form-live-component"
          form={@form}
          module={AnnaBailaWeb.FormLiveComponent}
        />
      </div>
    </div>
    """
  end
end

defmodule FormRecoverableWeb.FormLiveComponent do
  @moduledoc false

  use FormRecoverableWeb, :live_component

  @impl true
  def update(_assigns, socket) do
    {:ok, assign(socket, :form, to_form(%{"username" => nil}))}
  end

  @impl true
  def handle_event("validate", params, socket) do
    {:noreply, assign(socket, :form, to_form(params))}
  end

  def handle_event("submit", _params, socket), do: raise("break live component")

  @impl true
  def render(assigns) do
    ~H"""
    <div>
      <.simple_form
        id={"#{System.unique_integer()}"}
        for={@form}
        phx-submit="submit"
        phx-target={@myself}
        phx-change="validate"
      >
        <.input id="name-live-component" field={@form[:name]} label="name" />
        <:actions>
          <.button phx-disable-with="Saving...">Crash LiveComponent</.button>
        </:actions>
      </.simple_form>
    </div>
    """
  end
end

  • What am I doing wrong?
  • Is this expected behaviour or a bug?

Marked As Solved

champeric

champeric

I think the fix for your problem on 0.20.17 would be in commit 628f885, but this was done on the main branch, just after the latest release of 0.20.

Also Liked

joelpaulkoch

joelpaulkoch

Hello :wave:, can’t try it right now, but don’t you need to use the same id for the form in the live component? You will end up with a different id when you render the live component after the crash, no?

id={"#{System.unique_integer()}"}
benwilson512

benwilson512

Author of Craft GraphQL APIs in Elixir with Absinthe

You should still be generating distinct ids for each logical form in the assigns and then using that assign in the template. You’re going to get super weird behavior doing an impure call like that in the render itself, which is supposed to be deterministic from the assigns.

I can’t comment on the error you’re getting with a hard coded value, but I would definitely chase down that error and not go with an impure render, which is explicitly called out as a bad idea in the docs.

dimitarvp

dimitarvp

Upload it to YouTube and post link?

Whoops, I commented literally seconds after you edited your second comment.

Where Next?

Popular in Questions Top

nobody
How to bind a phoenix app to a specific ip address? could not find anything about that, nowhere, unfortunately, but for me this is quite...
New
marius95
Hello everyone, I try to use an Javascript Event Handler in my root.html.leex file. Therefore I created a function in the app.js file: ...
New
Tee
can someone please explain to me how Enum.reduce works with maps
New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lists...
New
LegitStack
I’m trying to make a websocket server in Phoenix or raw Elixir. I heard about gun, I think I could use cowboy, but since I’m not that sma...
New
Lily
In templates/appointment/index.html.eex: &lt;%= for appointment &lt;- @appointments do %&gt; &lt;tr&gt; &lt;td&gt;&lt;%= appoi...
New
joeerl
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers’ Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
New

Other popular topics Top

New
AstonJ
Posting this to see if we can make things easier for people to get into Neovim. If you use Neovim and have a favourite distro please let ...
New
ovidiubadita
Hey all, I discovered Elixir and I love it. I always wanted to learn a functional programming and I intended to go for Haskell, but afte...
New
gausby
I asked this very same question on twitter and got some interesting feedback, but I thought it would be a good question to ask here as we...
1207 39467 209
New
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
axelson
This post is a wiki (feel free to hit the edit button near the bottom right of this post to add your own changes!) This post collects co...
239 48342 226
New
PeterCarter
There are pre-rolled solutions for other frameworks that do work. However, Phoenix does not seem to have these. Have people had good expe...
New
JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1144 54120 245
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New

Latest on Elixir Forum

Elixir Forum

We're in Beta

About us Mission Statement