Flags
Common uses are passing in API keys, environment variables, and user data. This can be handy if you generate the HTML dynamically. They can also help us load cached information in this example.
The HTML is basically the same as before, but with an additional flags
argument to the Elm.Main.init()
function
In this example we are passing in the current time in milliseconds, but any JS value that can be JSON decoded can be given as a flag.
To handle flags on the Elm side, you need to modify your init
function a bit:
module Main exposing (..)
import Browser
import Html exposing (Html, text)
-- MAIN
main : Program Int Model Msg
main =
Browser.element
{ init = init
, view = view
, update = update
, subscriptions = subscriptions
}
-- MODEL
type alias Model = { currentTime : Int }
init : Int -> ( Model, Cmd Msg )
( { currentTime = currentTime }
)
-- UPDATE
type Msg = NoOp
update : Msg -> Model -> ( Model, Cmd Msg )
update _ model =
( model, Cmd.none )
-- VIEW
view : Model -> Html Msg
view model =
text (String.fromInt model.currentTime)
-- SUBSCRIPTIONS
subscriptions : Model -> Sub Msg
subscriptions _ =
Sub.none
I recommend checking out for a more interesting use of flags!
But what happens if init
says it takes an Int
flag, but someone tries to initialize with Elm.Main.init({ flags: "haha, what now?" })
?
Elm checks for that sort of thing, making sure the flags are exactly what you expect. Without this check, you could pass in anything, leading to runtime errors in Elm!
There are a bunch of types that can be given as flags:
Float
String
Maybe
List
Array
- tuples
- records
Json.Decode.Value
Many folks always use a Json.Decode.Value
because it gives them really precise control. They can write a decoder to handle any weird scenarios in Elm code, recovering from unexpected data in a nice way.
init : Int -> ...
0
=>0
7
=>7
3.14
=> error6.12
=> error
init : Maybe Int -> ...
null
=>Nothing
42
=>Just 42
"hi"
=> error
init : { x : Float, y : Float } -> ...
{ x: 3, y: 4, z: 50 }
=>{ x = 3, y = 4 }
{ x: 3, name: "tom" }
=> error{ x: 360, y: "why?" }
=> error
init : (String, Int) -> ...
['tom',42]
=>("Tom", 42)
["sue",33]
=>("Sue", 33)
["bob","4"]
=> error
Note that when one of the conversions goes wrong, you get an error on the JS side! We are taking the “fail fast” policy. Rather than the error making its way through Elm code, it is reported as soon as possible. This is another reason why people like to use Json.Decode.Value
for flags. Instead of getting an error in JS, the weird value goes through a decoder, guaranteeing that you implement some sort of fallback behavior.