Elm Line Charts Part I: Times and Timezones
data-visualization elmElm has a very fine third-party line chart library
which I've enjoyed using in my passion project,
Chicago Test Out. It's well-documented
as a library, but if I haven't used it in a while, I find myself struggling
to get started with it. I end up starting at the middle or near the end and
then clumsily working backwards from where I want to end up. For this reason,
I'm working on writing a step-by-step guide for working with
terezka/line-charts based on my own preferences and assuming a high-degree
of customization apart from the defaults, using
Chicago Test Out as a model.
One of my preferences is that a linechart almost always be used with time on the x-axis, and you can't use a time without knowing the time zone, so we'll start there.
Step 1: Add a Time.Zone field to your model.
Timezones have to be fetched asynchronously, which means
- Open the file that has your model record in it and, if you have not already,
import Time. - Add a field of type
Time.Zoneto yourModeltype record. - In your model initialization, initialize your timezone field to Time.utc.
- Compile.
If you haven't already used elm/time somewhere, the elm compiler may
object and insist that you install the dependency, which it will walk you
through Assuming you don't have a lot of different functions that initialize
a new
model, this should bring your code to a compiling state. I am including the
full source for src/Models.elm from Chicago Test out below for reference.
module Models exposing (..)
import Hospitalization exposing (Hospitalization)
import TestDay exposing (TestDay)
import Time
type alias Model =
{ days : List TestDay
, hospitalizations : List Hospitalization
, mode : Mode
, zone: Time.Zone
}
type Mode = Test | HospitalizationMode
init : Model
init =
{ days = []
, hospitalizations = []
, mode = Test
, zone = Time.utc
}
Step 2: Add a time zone update message
- Open the file containing your Elm messages. (Mine is in src/Msg.elm.)
- If you haven't already,
import Timeinto that module. - Add an
UpdateZonetype that takes aTime.Zoneparameter, like so:
module Msg exposing (..)
import Hospitalization exposing (Hospitalization)
import Http
import Json.Encode
import Models exposing (Mode(..))
import RawTestDay exposing (RawTestDay)
import Time
type Msg = GotRawTestDays (Result Http.Error (List RawTestDay))
| SetMode Mode
| UpdateHospitalizationDays Json.Encode.Value
| UpdateZone Time.Zone
- Implement your new message in your
updatemethod of your elm application, likely located in src/Main.elm. (You may need toimport Timehere as well.) - Compile.
Your code should be once again in a compiling state.
Get the Timezone from a Task
Now, just hook a
Task to get
Time.here into your new message, and you should be up and running with
time zones.
This example shows how to do
it from init, but in Chicago Test Out, I want to fetch the time zone after
I've run a fetch, so I'm going to hook in from the end of my fetch event.
This is what I mean:
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
case msg of
GotRawTestDays result ->
case result of
Ok response ->
TestDay.fromRaws response
|> \days -> ({model | days = days}
, Task.perform UpdateZone Time.here
)
Err e ->
case e of
.
.
.
That's a lot to look at, but as you can see I'm calling Task.perform if the
response from GotRawTestDays is Ok. If the Task is successfull, the
current time zone, Time.here will be passed to the message handler of
UpdateZone.
A word on modeling times in Elm
As a reminder, Elm rejects ISO 8601 as a standard for dates. If you want dates
along the x-axis of your chart, you need to have those dates passed as a
posix number. For line charts, this should be a Float type. The steps to
get your data will vary, so I won't enumerate them here, but keep that in mind
as you work on fetching your line chart dataset: You need a Float for a date.
In Conclusion
This pretty well covers our prerequisites for working with line charts. In the next post, I'll start to scaffold a real chart.
I write to learn, so I welcome your constructive criticism. Report issues on GitLab.