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.


















