Working in a LiveComponent, is there a way to merge updates to assigns with the existing assigns once the data arrives?
For example, if I have two inputs, a URL input url
and a text input title
. I’m handling a blur event on the URL input which will asynchronous populate the title text input, but I’d like to allow the user to continue to modify the form as they desire.
def handle_event("url_blur", %{"value" => url}, socket) do
pid = self()
Task.async(fn ->
title = fetch_title(url)
send_update(
pid,
__MODULE__,
socket.assigns
|> assign(id: socket.assigns.id, loading: false)
|> update(:changeset, fn c ->
c
|> Ecto.Changeset.put_change(:title, title)
end)
)
end)
{:noreply, assign(socket, loading: true)}
end
I set loading to true so I can indicate that to the user and I send an asynchronous update to assigns with a change to the changeset. However, if there is user input on other inputs in the same form/changeset before the asynchronous changeset update arrives, that user input is unfortunately wiped once the change to title
finally occurs.
I have attempted a few variations of this, such as adding the values to assigns and then performing the changeset update in the live_component’s update/2
. However, I’m not able to find a way to merge the asynchronous changeset. Is there another approach I’m not thinking of?
I haven’t yet tried the independent pubsub approach because I’m not certain it will work any differently, and it will require significant refactoring because my form as a live_component
is used in multiple contexts. Will I be required to use a live_view
with a pubsub?