SPA in Elm: Part 1
Basic Elm Application Structure
Now we are ready to start with our first step in developing our application. We are starting with a very simple application which will just count number of button clicks. For now it’s enough to understand how elm architecture performs, but later we’ll use this first example as our screen in more complex multiscreen app. I don’t like very long code files, that’s why I always try to split code into as small as possible logical parts. Let’s start.
What is inside?
Elm architecture is good defined. You can see application structure at the top of this post. Elm is MVC framework and programming language in one bottle. Typical application consists of
- Main module which defines the application structure and startup behaviour,
- View module for UI related code
- Model describes all your internal state data
- Update is for handling events and updating Model according to them
- Subscription is for connecting recurring events and data streams to your app
- Port is for connecting with outer JS world
We won’t discuss last two modules in this exact article, let’s give them a chance next time, but trust me they are very useful in some cases.
Code
As there is no way to include different files form one Gist to different places of article, here is all code. Comments will be under it.
How all this works?
All this stuff at the end compiles to Html and JS. After you point your browser onto your html file, native JS part loads elm runtime gives it a node of DOM to use for it’s UI and calls Main.main function. There are several definitions of this function and several ways to call it from JS, but for now we will use one of the most common. In next part we’ll discuss another one, that is more advanced. You can see Main module and corresponding HTML/JS code above in “Code” section.
This code tells Elm runtime what functions to use for you application’s View and Update, what events to Subscribe and how to initiate it.
In Main.init function return instructs Elm runtime about 2 things:
- defines initial Model values. We set our counter to 0 here;
- instructs Elm runtime what actions to perform at application start. In our case we don’t need any actions and the list is empty.
After everything is ready the flow is the following:
- Update handles messages sent from Elm runtime and updates Model
- View renders or changes virtual DOM, to be more precise, on each update of Model
- When any user action occurred in UI Elm runtime sends message to Update
Let’s now look at each part in more details.
Model
Model is a backbone of your Elm application. It stores all internal state data for you. Nothing can be done in Elm without using the model. When some event occurs it can do nothing, but update the model. UI can’t be changed directly, it’s just rendered by View based on data from model.
The code is pretty simple, as our app is very simple. It just stores our button click counter as Int value.
View
View is a function that converts Model to human comfort interface. Most of it is just HTML expressed in Elm. But it’s only in our case. We’ll see more advanced View in Part 3 of this tutorial.
The most interesting place is onClick attribute of our button. It takes Msg constructor as an argument. We define Msg constructor when we define Msg type. You can imagine this is just like a message that is sent to Update when user clicks the button.
Update
This is a place where all magic with event messages takes place. Anything event that is happening in Elm runtime can be converted to message and received in Update. This messages are sent buy UI events from View as we saw before, from Subscriptions, from actions performed in Main.init and from even Update itself. All this messages are defined here as a type and function that accepts values of this type as second argument. This function returns same things as Main.init:
- transformed Model which is new app state;
- tasks for Elm runtime to perform.
In our case Update is pretty simple. We’ll make it more advanced in next part when we’ll add routing.
The only message our app’s Update accepts is ButtonClick, that increments counter in Model.
PS
Dear readers, thank you for your interest and feedback. I was very glad to see so much interest about my Previous article. If you like this one you are welcome to clap, subscribe and connect me. I’m waiting for new feedback!
You can contact me on Twitter (@t0ha666), Reddit (/u/t0ha), Telegram (t.me/war1and) or Email (t0hashvein@gmail.com).