Charts for live view

Hey guys!

I want to create a toy project that shows a chart of temperature over time and updates every 5 seconds. I feel LiveView is perfect for that use case because there will always be only one piece of data appended on the right side of the chart, and one piece of data deleted on the left.

However, most JS libraries I tried don’t do it this way. They need to take all data and call chart.update rerendering the entire chart. I also need to bypass LiveView with a channel to call that update function.

I wondered if you know any solutions that could use the power of LiveView in full :slight_smile:
Maybe you had experience with charts using SVG?
Or had a chart with only HTML divs and CSS?

1 Like

You can do

<div data-chart="<%= Jason.encode(@data) %>" phx-update="ignore" phx-hook="MyChart">
  <%# mount js chart inside here %>
</div>

The js hook will be called each time when data-chart is updated and phx-update="ignore" does not prevent the attribute from being updates, but probably only it’s children. So you can use the update callback of the js hook to update the chart with new data.

I’d strongly recommend to stick to svg for graphics. I’ve done some experiments with svgs in liveviews and it works quite well if you know how to handle svg. Only downside is that charts most often aren’t just the svg part, but also quite a lot of interaction like labels, tooltips and such things, which are imho not really a good fit for being handled by liveview, so a proper charting library might still be a good idea.

If you still want to go the route of creating the svg/interaction manually: I’ve tried out the technique of the start of this post with svelte.js – which works kinda similar to liveview, but on the client side. It allows you to add pure client side interactions, while still easily being able to receive updates to data from the liveview. There are some good examples for building charts with the low level pieces of d3 on the svelte website, but it can also do custom svg content.

10 Likes

Thank you! I wasn’t aware of phx-hook. I was plaing with LiveView before 2.0 and I missed that update.
This will be helpful!

Also, @sasajuric has some bespoke SVG chart rendering in the source code from one of his awesome talks that might be suitable. It’s not the centre piece of the talk. The leex template is here https://github.com/sasa1977/demo_system/blob/master/example_system/lib/example_system_web/load/graph.html.leex

Finally, if you are happy to homebrew SVG you could take a look at some D3.js samples - I’ve been porting bits and pieces of the scale and axis libraries over to elixir (not too embarrassing but not ready to release yet). If you want to get really deep, search for papers by Hadley Wickham, author of ggplot (an R library providing a nice abstraction for translating data into graphics). I’m trying to build a “charting” library in elixir with ggplot type concepts, learning SVG and layout tricks from D3 (as R code is mighty hard to read with my level of knowledge). It’s happening in fits and starts due to many other commitments. If it ever gets to a reasonable state I’ll let you know - I started on it because I think backend rendered real-time dashboards would be awesome!

7 Likes

Just found chartkick-ex (hex.pm). Have anybody of you tried it with LiveView? I’m thinking to rewrite our client side to LiveView where we have a plenty charts (all realtime measured data)…

2 Likes

SVG charts in Elixir is something I would love to see.

4 Likes

Putting out SVG is pretty much what my PlotEx library linked above does. Apply a few css rules and you can style it however it suits you. Using it with LiveView readily enables live updating! Just plug it in and go.

I’m using a 1 second :tick timer in my LiveView which just takes a new data stream and puts it in an assigns. It’s pretty decent speed for having essentially no optimizations. It runs fine on a raspberry pi embedded, but I haven’t checked the per-user memory usage but I suspect it’s competitive with a JS solution as it doesn’t have to serialize the data and have JS regenerate everything.

I’d like to have time to expand on the api and add more graph types. Elixir Streams make it trivial to say take time series data over days and only show every X’th item. Still if anyone is interested I’d love feedback on how to clean up the API or support more graph types. See the SVG Output module.

3 Likes