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,437