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:

    1. module Main exposing (..)
    2. import Browser
    3. import Html exposing (Html, text)
    4. -- MAIN
    5. main : Program Int Model Msg
    6. main =
    7. Browser.element
    8. { init = init
    9. , view = view
    10. , update = update
    11. , subscriptions = subscriptions
    12. }
    13. -- MODEL
    14. type alias Model = { currentTime : Int }
    15. init : Int -> ( Model, Cmd Msg )
    16. ( { currentTime = currentTime }
    17. )
    18. -- UPDATE
    19. type Msg = NoOp
    20. update : Msg -> Model -> ( Model, Cmd Msg )
    21. update _ model =
    22. ( model, Cmd.none )
    23. -- VIEW
    24. view : Model -> Html Msg
    25. view model =
    26. text (String.fromInt model.currentTime)
    27. -- SUBSCRIPTIONS
    28. subscriptions : Model -> Sub Msg
    29. subscriptions _ =
    30. 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:

    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 => error
      • 6.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.