Dealing with time in Elm
Note: This post was written for Elm 0.16
. There is now an
official documentation for dealing with time
in the latest version.
Because Elm is based on functional reactive programming concepts, dealing with time is different to most other programming languages I have worked with. Although it might be unfamiliar at first I think the way Elm handles time is simpler. When I first stumbled upon the problem it took a while to get some time-based logic working. If you are new to Elm like I am, I thought a basic example might help you to understand it.
#Goal
The simplest example I could think of is an app that does the following:
- user clicks a button
- button hides for 5 seconds
- and shows up again
The whole example code is open source
on GitHub. Coming from a JavaScript background I also like to render actual HTML
elements and use the StartApp
package for easy extension.
#Inputs in StartApp
If you don’t know how the StartApp
package works I recommend reading my
tutorial on
making HTTP requests in Elm
first.
The Elm core library includes a
time library.
To get the current time there is
Time.every
,
which returns a stream of timestamps. Streams can be added to Elm apps via
inputs
using StartApp
:
inputs =
[
Signal.map UpdateTime
<| Time.every Time.millisecond
]
This code creates a stream with Time.every Time.millisecond
. Then I map over
this stream and wrap every timestamp with an UpdateTime
action, as inputs
requires a list of action Signals.
#Storing time in the model
Everytime update
receives an UpdateTime
action it stores the passed
timestamp in the model. This can now be used in the view
function to display
the current time or for doing other logic with it whenever an action comes in.
UpdateTime time ->
{ model | time = time }
I also added another action UpdateTimestamp
to store a specific timestamp,
which is used to toggle the visibility of the button. It takes the current time
from the model, adds 5000 milliseconds and stores this timestamp in the model as
well:
UpdateTimestamp ->
{ model | timestamp = model.time + 5000 }
#Hiding the button
The view
function now receives everything it needs to compute the difference
between model.time
and model.timestamp
which decides when to hide or show
the button:
if model.time - model.timestamp > 0 then
button [ onClick address UpdateTimestamp ] [ text "wait 5 seconds" ]
else
node "noscript" [] []
I used <noscript>
here to not display anything while the button is hidden.
When the button is shown, clicks send the UpdateTimestamp
action, which
updates model.timestamp
and therefore hides the button for the next 5 seconds.
#Conclusion
Once there is an always up-to-date timestamp in the app’s model, it is easy to deal with time in Elm. I hope this example could get you started with adding time based logic to your Elm applications. As mentioned earlier the full example code is on GitHub.