I have pretty basic live view listing todos and having “new todo” with a popup. Upon submitting, the default behavior (result of phoenix generators) is calling push_redirect
back to index. However, this seems to be triggering full page reload (load indicator on top, phx_leave -> phx_close -> phx_join in websocket). This is not desired behavior, not sure if it’s caused by my mistake.
So I am trying to use push_patch
instead, but I am having trouble seeing the newly added todo on the index page. I tried an approach described here in docs, with temporary assigns and phx-update="append"
in the template – that will write the new todo to database, but it won’t show up on screen (I did update id’s in template). Also deleting todos doesn’t have visible effect, just database deletion.
I also tried phx-update="replace"
in the template, which seems to work really nicely when deleting todos, but new todos still don’t appear… In both cases I see cids_destroyed
sent from client via websocket, no idea what that means and what’s causing it. But it seems to cause full page reload, or at least very slow response.
mount
def mount(%{"list_id" => list_id}, _session, socket) do
socket =
socket
|> assign(:todos, list_todos(list_id))
|> assign(:user, get_user(list_id))
|> assign(:list_id, list_id)
# clearing whichever flash message, after 3 seconds
if connected?(socket), do: Process.send_after(self(), :clear_flash, 3000)
# temporary assign for push_patch,
# not sure if needed when phx-update="replace" in the template
# {:ok, socket, temporary_assigns: [todos: []]}
{:ok, socket}
end
new todo action
defp apply_action(socket, :new, %{"list_id" => list_id} = params) do
socket
|> assign(:page_title, "New Todo")
# create empty Todo, pre-filled with list_id (hidden field in form)
|> assign(:todo, %Todo{list_id: list_id})
end
form component save todo with the infamous push_patch
defp save_todo(socket, :new, todo_params) do
case Lists.create_todo(todo_params) do
{:ok, _todo} ->
socket =
socket
# |> put_flash(:info, "Todo created successfully")
# add just the new todo, but not sure whether it makes sense with phx-update="replace"
# |> assign(:todos, todo)
|> push_patch(to: socket.assigns.return_to)
{:noreply, socket}
{:error, %Ecto.Changeset{} = changeset} ->
{:noreply, assign(socket, changeset: changeset)}
end
end
returns to index action
defp apply_action(socket, :index, %{"list_id" => list_id} = params) do
socket
|> assign(:page_title, "Listing Todos")
|> assign(:todo, nil) # clear for the form
|> assign(:todos, list_todos(list_id)) # TODO should this be here??
end
I am completely stuck at this point, can’t find any docs for cids_destroyed
that would help me fully understand. It seems like it could be something with id’s in the template, but no idea what I’m doing wrong there and how it should be done properly.
Also not exactly sure 1. where exactly to update list of all todos and assign it to socket and 2. what’s the difference between phx-update="append"
(just assigning 1 new todo to todos?) and phx-update="replace"
(sending all todos every time?) - especially what’s the difference between having “replace” vs having nothing at all.
Thank you very much for your help and guidance, sorry for long post!