Elm + Components = <3
How to integrate Elm in your current stack?
Tech Lead @ Meetic


k.lebrun@meetic-corp.com
kevinlebrun
Elm
Why Elm?
- Functional language that compiles to JavaScript
- A simple language
-
No `null`
- No runtime errors
- Architecture / Framework
One-way data flow
type alias Model = Int

type alias Model = { value = 0 }

Model
view : Model -> Html Msg
view model =
div []
[ button [ onClick Decrement ] [ text "-" ]
, span [] [ text (toString model) ]
, button [ onClick Increment ] [ text "+" ]
]

View
type Msg = Increment | Decrement
update : Msg -> Model -> Model
update msg model =
case msg of
Increment ->
model + 1
Decrement ->
model - 1

Update
main : Program Never
main =
beginnerProgram
{ model = 0
, view = view
, update = update
}

Main
Embed
var node = document.getElementById('counter');
Elm.Counter.embed(node);

Hello World!
Friendly error messages

Interop
How to communicate with the outside world?
Subscribe to changes
var node = document.getElementById('counter');
var app = Elm.Counter.embed(node);
app.ports.change.subscribe(function (value) {
console.log(value);
});

port change : Model -> Cmd msg

Dispatch changes
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
Increment ->
( model + 1, change model + 1 )
Decrement ->
( model - 1, change model - 1 )

Send messages
var node = document.getElementById('counter');
var app = Elm.Counter.embed(node);
app.ports.set.send(42);

port set : (Model -> msg) -> Sub msg

Accept external messages
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
Set value ->
( value, change value )

Set initial values
var node = document.getElementById('counter');
Elm.Counter.embed(node, { value: 42 });

Set initial values
init : { a | value : Int } -> ( Model, Cmd Msg )
init flags =
( flags.value, Cmd.none )

localStorage Use Case
var app = Elm.Main.fullscreen(localStorage.session || null);
app.ports.storeSession.subscribe(function(session) {
localStorage.session = session;
});
window.addEventListener("storage", function(event) {
if (event.storageArea === localStorage
&& event.key === "session") {
app.ports.onSessionChange.send(event.newValue);
}
}, false);

Web Component
HTML APIs
- Custom Element
- Shadow DOM
- HTML Templates
- HTML Imports
Polymer
Fancy buttons

paperCard = node "paper-card"
paperButton = node "paper-button"
heading = attribute "heading"
cardContent = div [ class "card-content" ]
cardActions = div [ class "card-actions" ]
view : Model -> Html Msg
view model =
div []
[ paperCard [ heading "Hello World!" ]
[ cardContent [ text (toString model) ]
, cardActions
[ paperButton [ onClick Decrement ] [ text "Decrement" ]
, paperButton [ onClick Increment ] [ text "Increment" ]
]
]
]

Fancy counter
Custom Event Handler
detailValue =
Json.at [ "detail", "value" ] Json.int
onValueChanged tagger =
on "value-changed" <| Json.map tagger detailValue

Conclusion
Q/A

github.com/kevinlebrun/elm-polymer
Elm + Components = <3
By Kevin Le Brun
Elm + Components = <3
How to integrate Elm in your current stack?
- 2,699