My live component is working as expected if I mount the live view using it directly (by accessing the corresponding route).
But when I navigate to the same live view from another one, the component only gets setup (mount/1
and update/2
are triggered), but none of the events fire. This happens also if I navigate away from the live view using the component and then back again.
{:phoenix, "~> 1.7.11"},
{:phoenix_ecto, "~> 4.5.1"},
{:phoenix_html, "~> 4.1.1"},
{:phoenix_live_reload, "~> 1.5", only: :dev},
{:phoenix_live_view, "~> 0.20.14"},
This is what the component looks like (maybe my hacky usage of forms and changeset is an issue?):
defmodule FieldPublicationWeb.PublicationLive.CommentsFormComponent do
alias Phoenix.HTML.Form
alias FieldPublication.Schemas.Translation
use FieldPublicationWeb, :live_component
def render(assigns) do
~H"""
<div>
<table class="w-full">
<thead>
<tr>
<th>Language</th>
<th>Text</th>
</tr>
</thead>
<tbody>
<%= for form <- @forms do %>
<.form
for={form}
id={"comment-#{form[:language].value}"}
phx-change="text_changed"
phx-target={@myself}
>
<tr>
<td>
<.input field={form[:language]} type="text" readonly />
</td>
<td>
<.input field={form[:text]} type="textarea" />
</td>
</tr>
</.form>
<% end %>
</tbody>
</table>
<%= if @changed do %>
<div
class="w-full text-center font-semibold font-mono"
phx-click="update_translations"
phx-target={@myself}
>
Set all
</div>
<% end %>
</div>
"""
end
def update(%{id: id, languages: language_options, translations: translations}, socket) do
forms =
Enum.map(language_options, fn lang_option ->
Enum.find(translations, fn %Translation{language: lang} ->
lang == lang_option
end)
|> case do
nil ->
%Translation{}
|> Translation.changeset(%{"language" => lang_option})
|> to_form()
%Translation{language: lang, text: text} ->
%Translation{}
|> Translation.changeset(%{"language" => lang, "text" => text})
|> to_form()
end
end)
{
:ok,
socket
|> assign(:id, id)
|> assign(:forms, forms)
|> assign(:changed, false)
}
end
def handle_event(
"text_changed",
%{"translation" => %{"language" => lang, "text" => text}},
%{assigns: %{forms: forms}} = socket
) do
forms =
Enum.map(forms, fn %Phoenix.HTML.Form{} = form ->
if Form.input_value(form, :language) == lang do
%Translation{}
|> Translation.changeset(%{"language" => lang, "text" => text})
|> to_form()
else
form
end
end)
{
:noreply,
socket
|> assign(:forms, forms)
|> assign(:changed, true)
}
end
def handle_event("update_translations", _params, socket) do
changesets =
Enum.map(socket.assigns.forms, fn form ->
Translation.changeset(%Translation{}, %{
"language" => Form.input_value(form, :language),
"text" => Form.input_value(form, :text)
})
end)
send(
self(),
{:update_translations, socket.assigns.id, changesets}
)
{:noreply, assign(socket, :changed, false)}
end
end
In my browser console I get the following log when using navigate:
phx-(..) destroyed: the child has been removed from the parent - undefined