brettinternet

brettinternet

Send_update to merge changes into assigns

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?

Marked As Solved

brettinternet

brettinternet

Yes, sending a message to the LiveView is the only method to asynchronously patch assigns. send_update will not work for this.

def handle_event("url_blur", %{"value" => url}, socket) do
  pid = self()
  
  Task.async(fn ->
    title = fetch_title(url)

    send(
      pid,
      {:update_changeset, title}
    )
  end)
  
  {:noreply, assign(socket, loading: true)}
end

def handle_info({:update_changeset, title}, socket) do
  changeset = socket.assigns.changeset
    |> Ecto.Changeset.put_change(:title, title)

  {:noreply, socket |> assign(changeset: changeset, loading: false)}
end

def handle_info(_, socket) do
  {:noreply, socket}
end

This is unfortunate because I had hoped to manage state in a LiveComponent.

Where Next?

Popular in Questions Top

New
dokuzbir
I want to highlight html closing tags when i click a html tag. That works in .html files but doesnt work for html.eex templates. How can...
New
Darmani72
If I have a post route which an argument: post /my_post_route/:my_param1, MyController.my_post_handler How would get the post params ...
New
electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
vac
Hi, I’m quite new in Elixir and I’m trying to format a string to a PEM format. I have the certificate value like MIIDBTCCAe2...... and I...
New
Lily
In templates/appointment/index.html.eex: <%= for appointment <- @appointments do %> <tr> <td><%= appoi...
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
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
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

Other popular topics Top

TunkShif
This post is an instruction guide to help you setup your Neovim for Elixir development from scratch. It includes general information on h...
274 41989 114
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? Ecto.Repo — Ecto v3.14.0 has exampl...
New
aesmail
Hello guys, I have finally made it. I created an admin interface for a framework. It’s been on my todo list for years and with the curre...
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
RisingFromAshes
I’ve read in another post that it may be possible with a router helper - but I couldn’t find an appropriate one, and tbh, I’m still just ...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New
klo
Got a question about when to concat vs. prepending items to list then reversing to achieve appending. So i know lists boil down to [1 | ...
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 records...
New
vegabook
I’m brand new to Phoenix and I have stripped one of the demo applications to the bone. I just want to get an svg up on the screen. Here i...
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