Las Flags o banderas permiten pasar valores a Elm durante la inicialización.
Usos comunes incluyen claves de API, variables de entorno y datos de usuario. Esto puede ser útil si se genera el HTML dinámicamente. También nos ayudan a cargar información almacenada en caché en este ejemplo de almacenamiento local.
El HTML es básicamente el mismo que antes, pero con un argumento adicional de banderas para la función Elm.Main.init().
<html>
<head>
<meta charset="UTF-8">
<title>Main</title>
<script src="main.js"></script>
</head>
<body>
<div id="myapp"></div>
<script>
var app = Elm.Main.init({
node: document.getElementById('myapp'),
flags: Date.now()
});
</script>
</body>
</html>
En este ejemplo, pasamos la hora actual en milisegundos, pero cualquier valor JS que pueda decodificarse en JSON puede utilizarse como indicador.
Estos datos adicionales se denominan "indicadores" porque son similares a los indicadores de la línea de comandos. Puedes llamar a elm make src/Main.elm, pero puedes añadir indicadores como --optimize y --output=main.js para personalizar su comportamiento.
Para gestionar las banderas en Elm, necesitas modificar ligeramente tu función init:
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 )
init currentTime =
( { currentTime = currentTime }
, Cmd.none
)
-- 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
Lo importante aquí es que la función init indica que acepta un argumento Int. Así es como el código de Elm obtiene acceso inmediato a las banderas que pasas desde JavaScript. Desde ahí, puedes añadir elementos a tu modelo o ejecutar comandos. Lo que necesites.
Pero, ¿qué sucede si init indica que acepta una bandera Int, pero alguien intenta inicializar con Elm.Main.init({ flags: "jaja, ¿y ahora qué?" })?
Elm comprueba este tipo de cosas, asegurándose de que las banderas sean exactamente las esperadas. Sin esta comprobación, podrías pasar cualquier cosa, lo que provocaría errores de ejecución en Elm. Hay varios tipos que se pueden usar como indicadores:
BoolIntFloatStringMaybeListArray- tuples
- records
Json.Decode.Value
Mucha gente siempre usa Json.Decode.Value porque les da un control muy preciso. Pueden escribir un decodificador para gestionar cualquier situación inusual en el código Elm, recuperándose de datos inesperados de forma sencilla.
Los demás tipos compatibles son anteriores a que se descubriera una forma de crear decodificadores JSON. Si decide usarlos, hay algunas sutilezas que debe tener en cuenta. Los siguientes ejemplos muestran el tipo de bandera deseado, y los subpuntos muestran qué sucedería con un par de valores JS diferentes:
init : Int -> ...0=>07=>73.14=> error6.12=> error
init : Maybe Int -> ...null=>Nothing42=>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["Joe", 9, 9]=> error
Ten en cuenta que cuando una conversión falla, se genera un error en el lado de JS. Adoptamos la política de "fallo rápido". En lugar de que el error se transmita por el código de Elm, se reporta lo antes posible. Esta es otra razón por la que se prefiere usar Json.Decode.Value para las banderas. En lugar de generar un error en JS, el valor inusual pasa por un decodificador, lo que garantiza la implementación de algún tipo de comportamiento alternativo.
