Automatically chart async data in liveview without user interaction

To do the initial one, you push an event in mount if it is a liveview or in update if it is a live component.

For example:

defmodule MyWeb.Components.Charts.EchartComponent do
  use MyWeb, :surface_live_component

  @doc "E-Charts `option` configuration map"
  prop option, :map, required: true

  @doc "Merge the option with the existing one (`true`), or replace it (`false`)?"
  prop merge, :boolean, default: true

  prop class, :css_class, default: "flex h-full w-full"

  def push_loading_event(socket, chart_id) when is_binary(chart_id) do
    push_event(socket, "echarts:#{chart_id}:loading", %{})
  end

  def push_update_event(socket, chart_id, %{"option" => _} = params) when is_binary(chart_id) do
    params = Map.put_new(params, "merge", true)
    push_event(socket, "echarts:#{chart_id}:update", params)
  end

  def push_init_event(socket, chart_id, %{"option" => _} = params) when is_binary(chart_id) do
    params = Map.put_new(params, "merge", true)
    push_event(socket, "echarts:#{chart_id}:init", params)
  end

  def update(%{id: id, option: option, merge: merge} = assigns, socket) do
    {:ok,
     socket
     |> assign(assigns)
     |> push_init_event(id, %{"option" => option, "merge" => merge})}
  end

  @impl true
  def render(assigns) do
    ~F"""
    <div phx-hook="Echarts" id={"echarts-#{@id}"} phx-update="ignore" class={@class} data-id={@id} />
    """
  end
end

In a liveview that uses this, I push “loading” on mount and when params are changed, I push “loading” again and call start_async to fetch the new data async. When it lands, I push an “update” event with the new data. Echarts has a built in show/hide loading indicator function which I’m using. You could a similar thing with the <.async_result> component.