tfwright

tfwright

LiveView learning application

I thought I’d share a small project I’m working on to gain some familiarty with LiveView in a Phoenix app.

Github Repo

Deployment

It’s a little timer designed around interval exercises. Basically it allows you to build a list of sets of timed exercise intervals, which can be repeated, with periods of rest in between each interval.

You can browse the commit history to see how the project developed. I started with a bare bones Ecto-less Phoenix app, and I just added a simple LiveView module to handle form events for the exercises. I also added a timer with controls that would loop through the data from the form and update the assigns sent to the view, allowing the user to see a count down.

As a next step I added the concept of ‘sets’ so that intervals could be grouped and repeated, with rest in between.

This was all (template, helpers, timer etc) in a single module, so finally I refactored a bit by pull out the different parts into separate files, namely, a template and helper file. If I continue, I will probably extract some of the data structures from the LiveView logic into schemas.

Overall, I’m quite impressed with LiveView. It was really nice not to have to wire a bunch of boilerplate JS API integration in order to see a working UX. I ran into a lot fewer typical issues with JS syntax errors, browser refreshing and console logging, etc. That whole painful process was just skipped. Conversely, I immediately ran into the typical challenges in managing state for a dynamic UX, immutable data updates, etc. I think that’s a good thing, because it brought the real problems in my domain into clearer focus, and let me bring the power of Elixir to bear in solving them, which for me was quite an advantage of any flavor of JS with any number of libraries assisting.

I should note that this application is probably not the ideal candidate for LiveView, since it requires a very long-running BEAM process just to countdown a timer, something that would probably be better handling on the client side so it takes up fewer server resources. But it was something I actually wanted to use so it gave me some motivation.

Hope this is of some help to anyone else interested in getting started with LiveView. Let me know your thoughts.

Most Liked

tfwright

tfwright

As promised, in the latest version I’ve converted some of the data structures into Ecto schemas. For extra learning, I put off actually setting up a Repo, and used embedded_schema for everything. It was pretty cool how easy it that was to accomplish.

On the LiveView side, this separation naturally created some separation in the UI, between the phase when a timer is being created and when it is being viewed/used. I took advantage of this by separating the form UI into a separate component. I began by trying to keep the change as incremental as possible by using LiveComponent to ‘embed’ the form into the timer view like it worked before, but that proved really awkward with the timer event handling. Again, this probably mostly shows that the timer logic shouldn’t be in Elixir at all and in a real application I probably would have converted it to JS at this time (if I hadn’t started there, which I almost certainly would have). But another easy solution was just to add a new top level live view for the timer, which I wanted anyway so that there would be a unique URL users could visit to reuse the same timer. Since this still isn’t backed by a DB, I added a simple Agent to store uuids.

Next step will probably be added some style/UI sugar so it’s a bit more usable, then maybe think about more permanent storage options. Rather than a relational DB, one option I’m considering is just adding a JSON export/import.

tfwright

tfwright

Latest update: JS beep sound alerts via Hooks.

Another “MVP” feature for this toy app is the ability to play sounds to alert the user when an interval is over. Can’t really expect someone that’s in the middle of a strenuous exercise to keep their eyes trained on a screen. So after adding bulma and smoothing out the design a bit (CSS ugh) I started looking into how to implement some sort of audio component.

First armed with what I thought was a prefab npm package, I utterly failed to get things working. Although I was able to require the package in app.js just fine, the function wasn’t behaving as expected in my .leex template. At first I thought I was having problems with my webpacker config (one of the many reasons I want to learn LV in the first place), but actually I think the issue is with how LV injects its own scripts into the page.

After reading a bit, specifically @mindok’s very helpful posts here, it sounded like the easiest way to manage template scripts is to use LV’s hook API. And it turned out to be very easy. I just c/ped some SO code (as one does) and dropped it into the mounted hook for a span tag I would render when I wanted a beep.

Definitely unsure if it’s best practice to conditionally render tags with hooks assigned in this way. It’d definitely feels like a bit of an awkward work around, but seems to work pretty well. It’s also worth noting again that it is again the original bad design of implementing the timing code server-side that made this a problem in the first place. Good example of how not to architect a production app, but in this case that’s a good thing because the point is to learn and now I know about hooks (and it never hurts to get a reminder about the benefits of using the right tools either).

Link to deployed app is in the OP. If you have any experience using LV hooks and have an opinion about their proper use, lmk.

outlog

outlog

good fun with the beep - maybe just note ios and desktop safari is auto-muted:/

Where Next?

Popular in Guides/Tuts Top

OvermindDL1
Ran across this recently, it's a set of cheatsheet inforgraphic things of the OTP behaviours on the BEAM:
New
cheerfulstoic
I spent quite a bit of time trying to find a good configuration to build / test my Elixir app in CircleCI and then push an image to Docke...
New
hauleth
Some time ago someone suggested me to write article about how I have configured my Vim to work with Elixir, now there it is: https://med...
New
magnetic
Hey :wave:t3: Elixir community, I’ve been learning Elixir, and working on some side projects. My editor of choice is VSCode, and althoug...
New
hauks96
Hello everyone, I created a deployment tutorial for Phoenix applications with Kubernetes (microk8s) a few months back with the goal of s...
New
tonydang
I recently got inertia-phoenix (an Inertia.js adapter for Phoenix) working with Svelte. Setting up the server-side rendering (SSR) with S...
New
rogach
I’ve spent some time understanding how to do hot code reloading with releases built using mix release, and here I’d like to detail the st...
New
dkuku
I Created a blog post about setting up svelte with phoenix. I found it a bit tricky and the only blog post I found was written using som...
New
caspg
Hi everyone, I recently implemented a real-time search feature in a Phoenix application using LiveView and Tailwind, and I wanted to sha...
New
KoviRobi
Hi, I’ve written the following to debug function calls, not sure if it’s useful for anyone else, and if so should I put it somewhere? i...
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 41454 115
New
Fl4m3Ph03n1x
About me? ( if you have nothing better to do than reading about some random guy in the internet :stuck_out_tongue: ) Hello all, this is ...
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
pmjoe
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
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
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers' Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New
dblack
I’ve got an issue with an app and I’ve no idea of how to troubleshoot it. I’m hoping someone here might have seen something similar. I p...
New
jononomo
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
New

We're in Beta

About us Mission Statement