Sorry for the long post, I tried to give all the information and explain what I have already tried.
Problem: I put a classic phoenix view into a liveview. While everything seems fine, the echart just vanishes as soon as it's finished painting. There seems to be no way to get it back.
Here is my graph. As you can see, I try to also hook it to the phx:update
-event. But that doesn't help...
graph.js
:
updateGraph = function() {
console.log("updating the graph...")
let device_name = document.getElementById('device-name').value;
let series_data = document.getElementById('history_chart_data').dataset.series;
series_data = JSON.parse(series_data);
// draw chart
window.myChart.setOption({
[chart options omitted]
});
}
initGraph = function() {
// initialize echarts instance with prepared DOM
window.myChart = echarts.init(document.getElementById('history_chart'), 'light');
updateGraph();
}
document.addEventListener('DOMContentLoaded', initGraph, false);
document.addEventListener('phx:update', updateGraph);
Here is the html (graph.html.leex
). As you can see I even put the data in another div, just to be safe.
<%= if assigns[:ttnmessages] do %>
<script src="<%= Routes.static_path(DatabaumWeb.Endpoint, "/js/jcharts.min.js") %>"></script>
<script src="<%= Routes.static_path(DatabaumWeb.Endpoint, "/js/moment.min.js") %>"></script>
<script type="text/javascript" src="<%= Routes.static_path(DatabaumWeb.Endpoint, "/js/graph.js") %>"></script>
<div id="history_chart" style="width: 100%;height:50vh;"></div>
<div id="history_chart_data" data-series="<%= dataSeries(@ttnmessages, @graph_data) %>"></div>
<% end %>
And the liveview
defmodule AppWeb.ConsoleLive do
use Phoenix.LiveView
alias AppWeb.ConsoleView
alias App.API
def render(assigns) do
Phoenix.View.render(ConsoleView, "index.html", assigns)
end
@doc """
Graph
"""
def mount(session = %{params: %{"hardware_serial" => hardware_serial, "graph" => form}, user: current_user}, socket) do
AppWeb.Endpoint.subscribe("TtnMessages")
if connected?(socket), do: :timer.send_interval(1000, self(), :tick)
ttnmessages = API.list_ttnmessages(hardware_serial, form)
message = List.last(ttnmessages)
devices = API.list_message_devices(current_user)
device = API.get_device_by_serial(hardware_serial);
graph_data = form
|> Enum.reject(fn {_k, v} -> v != "true" end)
|> Enum.map(fn {k, _v} -> k end)
|> Enum.to_list()
session = Map.merge(session, %{
devices: devices,
ttnmessages: ttnmessages,
message: message,
device: device,
graph_data: graph_data,
message_ago: message_ago(message.inserted_at)
})
{:ok, assign(socket, session)}
end
#[Omitted two other mount methods, which are not called in this case]
# updates the info when the device has last been seen.
def handle_info(:tick, socket) do
message = socket.assigns[:message]
{:noreply, assign(socket, message_ago: message_ago(Map.get(message, :inserted_at)))}
end
#new message arrives, this is not responsible for my issue because this happens max. once per minute
def handle_info(%{event: "new", payload: %{message: message}} = a, socket) do
message = update_message(message, socket.assigns.message)
devices = Enum.map(socket.assigns.devices, &update_device(&1, message))
{:noreply, assign(socket, devices: devices, message: message)}
end
def handle_info(_broadcast, socket), do: {:noreply, socket}
# update the message if necessary
defp update_message(message = %{hardware_serial: hs}, socket_message = %{hardware_serial: hs}), do: message
defp update_message(_message, socket_message), do: socket_message
defp update_device(_device= %{hardware_serial: hs}, _message = %{hardware_serial: hs}), do: API.get_device_by_serial(hs)
defp update_device(device, _message), do: device
defp message_ago(nil), do: "never"
defp message_ago(date) do
{:ok, ago} = Timex.Format.DateTime.Formatters.Relative.relative_to(date, Timex.now(), "{relative}", "de")
ago
end
end
The ttnmessages are never even updated. The ttnmessage is updated rarely. The tick is not responsible, I tried disabling that.
The chart before it vanishes (during page load) and afterwards The interesting thing is that when I try to edit the element css and e.g. add a red background color, that when the tick hits.
Calling window.updateGraph()
from the browser console does not make the graph reappear, but prints out updating the graph...
.
As Chris McCord mentioned on Github, I had to insert phx-update="ignore"
into the graph html. This fixed the issue and made me very happy.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With