@rtfeldman - frontend masters · reverse : list val -> list val reverse : list thing -> list...

282
elm @rtfeldman

Upload: others

Post on 24-May-2020

26 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

elm@rtfeldman

Page 2: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

8. JavaScript Interop

Page 3: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

function guarantees

Page 4: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

same arguments?same return value

no side effects

Page 5: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

Math.random()

Page 6: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

localStorage.foo = "bar";

Page 7: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

access huge JS ecosystem

Page 8: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

while maintaining guarantees

access huge JS ecosystem

Page 9: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

"client/server" communication

Page 10: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

"client/server" communication

Elm sends data to JS

JS sends data to Elm

Page 11: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

"client/server" communication

Elm sends data to JS

JS sends data to Elmno direct function calls

Page 12: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

Cmd on the Elm side

callback on JS side

Page 13: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

Cmd Msg

Page 14: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

Cmd Msg

Cmd msg

Page 15: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

type variables

Page 16: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

List.reverse [ "foo", "bar", "baz" ] == [ "baz", "bar", "foo" ]

List.reverse [ 1.1, 2.2, 3.3 ] == [ 3.3, 2.2, 1.1 ]

List.reverse [ True, False, False ] == [ False, False, True ]

Page 17: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

reverse :

Page 18: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

reverse : List ??? -> List ???

Page 19: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

reverse : List val -> List val

Page 20: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

reverse : List val -> List val

type variable

Page 21: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

reverse : List val -> List val

reverse : List thing -> List thing

reverse : List a -> List a

Page 22: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

elmHubHeader : Html MsgelmHubHeader = header [] [ h1 [] [ text "ElmHub" ] , span [ class "tagline" ] [ text "Like GitHub..." ] ]

Page 23: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

elmHubHeader : Html MsgelmHubHeader = header [] [ h1 [] [ text "ElmHub" ] , span [ class "tagline" ] [ text "Like GitHub..." ] ]

"this is compatible with Html that produces Msg"

Page 24: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

elmHubHeader : Html msgelmHubHeader = header [] [ h1 [] [ text "ElmHub" ] , span [ class "tagline" ] [ text "Like GitHub..." ] ]

Page 25: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

elmHubHeader : Html aelmHubHeader = header [] [ h1 [] [ text "ElmHub" ] , span [ class "tagline" ] [ text "Like GitHub..." ] ]

Page 26: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

Cmd Msg

produces messages of type Msg

Page 27: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

Cmd Msg

works with update functions that accept Msg

produces messages of type Msg

Page 28: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

Cmd Msg

Cmd msgworks with any update function

Page 29: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

Cmd Msg

Cmd msgworks with any update function

...because it never produces any messages!

Page 30: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

the port keyword

&

index.html

Page 31: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

subscriptions

Page 32: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

viewupdate

Msg Html Msg

Elm Runtime

Cmd Msg

Model

Page 33: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

viewupdate

Msg Html Msg

Elm Runtime

Cmd Msg

Modelsubscriptions

Page 34: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

viewupdate

Msg Html Msg

Elm Runtime

Cmd Msg

Modelsubscriptions Msg

Page 35: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

viewupdate

Msg Html Msg

Elm Runtime

Cmd Msg

Modelsubscriptions Msg

Model

Page 36: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

github.js

Page 37: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

Exercise: resolve the TODOs in part8

decodeString responseDecoder json

decodeValue responseDecoder json

Page 38: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

9. Testing

Page 39: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

{ "version": "1.0.0", "summary": "Like GitHub, but for Elm stuff.", "repository": "https://github.com/rtfeldman/elm-workshop.git", "license": "BSD-3-Clause", "source-directories": [ ".", ".." ], "exposed-modules": [], "dependencies": { "NoRedInk/elm-decode-pipeline": "1.1.2 <= v < 2.0.0", "elm-lang/core": "4.0.1 <= v < 5.0.0", "elm-lang/html": "1.0.0 <= v < 2.0.0", "evancz/elm-http": "3.0.1 <= v < 4.0.0" }, "elm-version": "0.17.0 <= v < 0.18.0"}

elm-package.json

Page 40: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

{ "version": "1.0.0", "summary": "Like GitHub, but for Elm stuff.", "repository": "https://github.com/rtfeldman/elm-workshop.git", "license": "BSD-3-Clause", "source-directories": [ ".", ".." ], "exposed-modules": [], "dependencies": { "NoRedInk/elm-decode-pipeline": "1.1.2 <= v < 2.0.0", "elm-lang/core": "4.0.1 <= v < 5.0.0", "elm-lang/html": "1.0.0 <= v < 2.0.0", "evancz/elm-http": "3.0.1 <= v < 4.0.0" }, "elm-version": "0.17.0 <= v < 0.18.0"}

elm-package.json

Page 41: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

{ "version": "1.0.0", "summary": "Like GitHub, but for Elm stuff.", "repository": "https://github.com/rtfeldman/elm-workshop.git", "license": "BSD-3-Clause", "source-directories": [ ".", ".." ], "exposed-modules": [], "dependencies": { "NoRedInk/elm-decode-pipeline": "1.1.2 <= v < 2.0.0", "elm-lang/core": "4.0.1 <= v < 5.0.0", "elm-lang/html": "1.0.0 <= v < 2.0.0", "evancz/elm-http": "3.0.1 <= v < 4.0.0" }, "elm-version": "0.17.0 <= v < 0.18.0"}

elm-package.json

Page 42: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

elmHub/ elm-package.json Main.elm ElmHub.elm

Page 43: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

{ "version": "1.0.0", "summary": "Like GitHub, but for Elm stuff.", "repository": "https://github.com/rtfeldman/elm-workshop.git", "license": "BSD-3-Clause", "source-directories": [ ".", ".." ], "exposed-modules": [], "dependencies": { "NoRedInk/elm-decode-pipeline": "1.1.2 <= v < 2.0.0", "elm-lang/core": "4.0.1 <= v < 5.0.0", "elm-lang/html": "1.0.0 <= v < 2.0.0", "evancz/elm-http": "3.0.1 <= v < 4.0.0" }, "elm-version": "0.17.0 <= v < 0.18.0"}

elm-package.json

Page 44: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

{ "version": "1.0.0", "summary": "Like GitHub, but for Elm stuff.", "repository": "https://github.com/rtfeldman/elm-workshop.git", "license": "BSD-3-Clause", "source-directories": [ ".", ".." ], "exposed-modules": [], "dependencies": { "NoRedInk/elm-decode-pipeline": "1.1.2 <= v < 2.0.0", "elm-lang/core": "4.0.1 <= v < 5.0.0", "elm-lang/html": "1.0.0 <= v < 2.0.0", "evancz/elm-http": "3.0.1 <= v < 4.0.0" }, "elm-version": "0.17.0 <= v < 0.18.0"}

elm-package.json

Page 45: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

{ "version": "1.0.0", "summary": "Like GitHub, but for Elm stuff.", "repository": "https://github.com/rtfeldman/elm-workshop.git", "license": "BSD-3-Clause", "source-directories": [ ".", ".." ], "exposed-modules": [], "dependencies": { "NoRedInk/elm-decode-pipeline": "1.1.2 <= v < 2.0.0", "elm-lang/core": "4.0.1 <= v < 5.0.0", "elm-lang/html": "1.0.0 <= v < 2.0.0", "evancz/elm-http": "3.0.1 <= v < 4.0.0" }, "elm-version": "0.17.0 <= v < 0.18.0"}

elm-package.json

Page 46: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

"NoRedInk/elm-decode-pipeline": "1.1.2 <= v < 2.0.0"

Page 47: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

"NoRedInk/elm-decode-pipeline": "1.1.2 <= v < 2.0.0"

Page 48: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

"NoRedInk/elm-decode-pipeline": "1.1.2 <= v < 2.0.0"

Page 49: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

"NoRedInk/elm-decode-pipeline": "1.1.2 <= v < 2.0.0"

Page 50: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

"NoRedInk/elm-decode-pipeline": "1.1.2 <= v < 2.0.0"

1.1.2major minor patch

Page 51: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

"NoRedInk/elm-decode-pipeline": "1.1.2 <= v < 2.0.0"

1.1.2major minor patch

semantic versioning automatically enforced

Page 52: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

elmHub/ elm-package.json Main.elm ElmHub.elm

Page 53: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

elmHub/ elm-package.json Main.elm ElmHub.elm

tests/ elm-package.json Main.elm Tests.elm

Page 54: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

"source-directories": [ ".", ".."],"dependencies": { "NoRedInk/elm-decode-pipeline": "1.1.2 <= v < 2.0.0", "elm-community/elm-test": "2.0.1 <= v < 3.0.0", "elm-lang/core": "4.0.1 <= v < 5.0.0", "elm-lang/html": "1.0.0 <= v < 2.0.0", "evancz/elm-http": "3.0.1 <= v < 4.0.0", "rtfeldman/html-test-runner": "1.0.0 <= v < 2.0.0", "rtfeldman/node-test-runner": "2.0.0 <= v < 3.0.0"}

tests/elm-package.json

tests

Page 55: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

"source-directories": [ ".", ".."],"dependencies": { "NoRedInk/elm-decode-pipeline": "1.1.2 <= v < 2.0.0", "elm-community/elm-test": "2.0.1 <= v < 3.0.0", "elm-lang/core": "4.0.1 <= v < 5.0.0", "elm-lang/html": "1.0.0 <= v < 2.0.0", "evancz/elm-http": "3.0.1 <= v < 4.0.0", "rtfeldman/html-test-runner": "1.0.0 <= v < 2.0.0", "rtfeldman/node-test-runner": "2.0.0 <= v < 3.0.0"}

tests/elm-package.json

testsmain source

Page 56: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

"source-directories": [ ".", ".."],"dependencies": { "NoRedInk/elm-decode-pipeline": "1.1.2 <= v < 2.0.0", "elm-community/elm-test": "2.0.1 <= v < 3.0.0", "elm-lang/core": "4.0.1 <= v < 5.0.0", "elm-lang/html": "1.0.0 <= v < 2.0.0", "evancz/elm-http": "3.0.1 <= v < 4.0.0", "rtfeldman/html-test-runner": "1.0.0 <= v < 2.0.0", "rtfeldman/node-test-runner": "2.0.0 <= v < 3.0.0"}

tests/elm-package.json

Page 57: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

"source-directories": [ ".", ".."],"dependencies": { "NoRedInk/elm-decode-pipeline": "1.1.2 <= v < 2.0.0", "elm-community/elm-test": "2.0.1 <= v < 3.0.0", "elm-lang/core": "4.0.1 <= v < 5.0.0", "elm-lang/html": "1.0.0 <= v < 2.0.0", "evancz/elm-http": "3.0.1 <= v < 4.0.0", "rtfeldman/html-test-runner": "1.0.0 <= v < 2.0.0", "rtfeldman/node-test-runner": "2.0.0 <= v < 3.0.0"}

tests/elm-package.json

Page 58: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

package.elm-lang.org

Page 59: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

unit tests

Page 60: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

"[ 1, 2, 3 ]" |> decodeString (list int) |> Expect.equal (Ok [ 1, 2, 3])

Page 61: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

expectation : Expectation expectation = "[ 1, 2, 3 ]" |> decodeString (list int) |> Expect.equal (Ok [ 1, 2, 3])

Page 62: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

\throwawayArgument -> "[ 1, 2, 3 ]" |> decodeString (list int) |> Expect.equal (Ok [ 1, 2, 3])

Page 63: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

() empty tuple, aka "Unit"

\throwawayArgument -> "[ 1, 2, 3 ]" |> decodeString (list int) |> Expect.equal (Ok [ 1, 2, 3])

Page 64: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

\() -> "[ 1, 2, 3 ]" |> decodeString (list int) |> Expect.equal (Ok [ 1, 2, 3])

Page 65: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

test "it successfully decodes" ( \() -> "[ 1, 2, 3 ]" |> decodeString (list int) |> Expect.equal (Ok [ 1, 2, 3]) )

Page 66: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

[ 2, 4, 6, 8 ] |> List.filter (\num -> num < 5) |> List.reverse

Page 67: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

[ 2, 4, 6, 8 ] |> List.filter (\num -> num < 5) |> List.reverse

List.reverse (List.filter (\num -> num < 5) [ 2, 4, 6, 8 ])

Page 68: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

[ 2, 4, 6, 8 ] |> List.filter (\num -> num < 5) |> List.reverse

List.reverse (List.filter (\num -> num < 5) [ 2, 4, 6, 8 ])

List.reverse <| List.filter (\num -> num < 5) [ 2, 4, 6, 8 ]

Page 69: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

test "it successfully decodes" ( \() -> "[ 1, 2, 3 ]" |> decodeString (list int) |> Expect.equal (Ok [ 1, 2, 3]) )

Page 70: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

test "it successfully decodes" <| \() -> "[ 1, 2, 3 ]" |> decodeString (list int) |> Expect.equal (Ok [ 1, 2, 3])

Page 71: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

describe "decoder tests" [ test "it successfully decodes" <| \() -> "[ 1, 2, 3 ]" |> decodeString (list int) |> Expect.equal (Ok [ 1, 2, 3]) ]

Page 72: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

describe "all my tests" [ describe "decoder tests" [ test "it successfully decodes" <| \() -> "[ 1, 2, 3 ]" |> decodeString (list int) |> Expect.equal (Ok [ 1, 2, 3]) ] ]

Page 73: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

test "Reversing twice does nothing" <| \() -> [ 1, 2, 3 ] |> List.reverse |> List.reverse |> Expect.equal [ 1, 2, 3 ]

Page 74: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

fuzz int "Reversing twice does nothing" <| \randomInt -> [ 1, 2, randomInt ] |> List.reverse |> List.reverse |> Expect.equal [ 1, 2, randomInt ]

Page 75: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

fuzz (list int) "Reversing twice does nothing" <| \randomList -> randomList |> List.reverse |> List.reverse |> Expect.equal randomList

Page 76: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

fuzz2 int float "Integers are bigger than floats" <| \randomInt randomFloat-> randomInt |> Expect.greaterThan randomFloat

Page 77: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

fuzz2 int float "Integers are bigger than floats" <| \randomInt randomFloat-> randomInt |> Expect.greaterThan randomFloat

Exercise: resolve the TODOs in part9

test "it decodes successfully" <| \() -> "[ 1, 2, 3 ]" |> decodeString (list int) |> Expect.equal (Ok [ 1, 2, 3])

Page 78: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

10. Delegation

Page 79: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

Adding Search Options

Page 80: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

Adding Search OptionssearchIn

userFilterminStars

Page 81: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

type Msg = Search | SetQuery String | DeleteById Int | SetMinStars Int | SetSearchIn String | SetUserFilter String

type alias Model = { query : String , results : List SearchResult , errorMessage : Maybe String , minStars : Int , searchIn : String , userFilter : String }

Page 82: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

type Msg = Search | SetQuery String | DeleteById Int | SetMinStars String | SetSearchIn String | SetUserFilter String

type alias Model = { query : String , results : List SearchResult , errorMessage : Maybe String , minStars : Int , minStarsError : Maybe String , searchIn : String , userFilter : String }

Page 83: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

type Msg = Search | SetQuery String | DeleteById Int | SetMinStars String | SetSearchIn String | SetUserFilter String

type alias Model = { query : String , results : List SearchResult , errorMessage : Maybe String , minStars : Int , minStarsError : Maybe String , searchIn : String , userFilter : String }

Page 84: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

type Msg = Search | SetQuery String | DeleteById Int | SetMinStars String | SetSearchIn String | SetUserFilter String

type alias Model = { query : String , results : List SearchResult , errorMessage : Maybe String , minStars : Int , minStarsError : Maybe String , searchIn : String , userFilter : String }

Page 85: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

type Msg = Search | SetQuery String | DeleteById Int | SetMinStars String | SetSearchIn String | SetUserFilter String

type alias Model = { query : String , results : List SearchResult , errorMessage : Maybe String }

type alias SearchOptions = { minStars : Int , minStarsError : Maybe String , searchIn : String , userFilter : String }

Page 86: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

type Msg = Search | SetQuery String | DeleteById Int | SetMinStars String | SetSearchIn String | SetUserFilter String

type alias Model = { query : String , results : List SearchResult , errorMessage : Maybe String , options : SearchOptions }

type alias SearchOptions = { minStars : Int , minStarsError : Maybe String , searchIn : String , userFilter : String }

Page 87: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

type Msg = Search | SetQuery String | DeleteById Int | SetMinStars String | SetSearchIn String | SetUserFilter String

type alias Model = { query : String , results : List SearchResult , errorMessage : Maybe String , options : SearchOptions }

type alias SearchOptions = { minStars : Int , minStarsError : Maybe String , searchIn : String , userFilter : String }

input [] [ value model.sort, onInput SetSort ]

Page 88: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

type Msg = Search | SetQuery String | DeleteById Int | SetMinStars String | SetSearchIn String | SetUserFilter String

type alias Model = { query : String , results : List SearchResult , errorMessage : Maybe String , options : SearchOptions }

type alias SearchOptions = { minStars : Int , minStarsError : Maybe String , searchIn : String , userFilter : String }

input [] [ value model.options.sort, onInput SetSort ]

Page 89: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

type Msg = Search | SetQuery String | DeleteById Int | SetMinStars String | SetSearchIn String | SetUserFilter String

type alias Model = { query : String , results : List SearchResult , errorMessage : Maybe String , options : SearchOptions }

type alias SearchOptions = { minStars : Int , minStarsError : Maybe String , searchIn : String , userFilter : String }

Page 90: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

type Msg = Search | SetQuery String | DeleteById Int

type OptionsMsg = SetMinStars String | SetSearchIn String | SetUserFilter String

type alias Model = { query : String , results : List SearchResult , errorMessage : Maybe String , options : SearchOptions }

type alias SearchOptions = { minStars : Int , minStarsError : Maybe String , searchIn : String , userFilter : String }

Page 91: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

type Msg = Search | SetQuery String | DeleteById Int | Options OptionsMsg

type OptionsMsg = SetMinStars String | SetSearchIn String | SetUserFilter String

type alias Model = { query : String , results : List SearchResult , errorMessage : Maybe String , options : SearchOptions }

type alias SearchOptions = { minStars : Int , minStarsError : Maybe String , searchIn : String , userFilter : String }

Page 92: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

type Msg = Search | SetQuery String | DeleteById Int | Options OptionsMsg

type OptionsMsg = SetMinStars String | SetSearchIn String | SetUserFilter String

type alias Model = { query : String , results : List SearchResult , errorMessage : Maybe String , options : SearchOptions }

type alias SearchOptions = { minStars : Int , minStarsError : Maybe String , searchIn : String , userFilter : String }

input [] [ value model.options.sort, onInput SetSort ]

Page 93: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

type Msg = Search | SetQuery String | DeleteById Int | Options OptionsMsg

type OptionsMsg = SetMinStars String | SetSearchIn String | SetUserFilter String

type alias Model = { query : String , results : List SearchResult , errorMessage : Maybe String , options : SearchOptions }

type alias SearchOptions = { minStars : Int , minStarsError : Maybe String , searchIn : String , userFilter : String }

input [] [ value model.options.sort, onInput (Options SetSort) ]

Page 94: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

type OptionsMsg = SetMinStars String | SetSearchIn String | SetUserFilter String

type alias SearchOptions = { minStars : Int , minStarsError : Maybe String , searchIn : String , userFilter : String }

input [] [ value model.options.sort, onInput (Options SetSort) ]

viewOptions : Model -> Html Msg

Page 95: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

type OptionsMsg = SetMinStars String | SetSearchIn String | SetUserFilter String

type alias SearchOptions = { minStars : Int , minStarsError : Maybe String , searchIn : String , userFilter : String }

viewOptions options = input [] [ value options.sort, onInput SetSort ]

viewOptions : Model -> Html MsgviewOptions : SearchOptions -> Html OptionsMsg

input [] [ value model.options.sort, onInput (Options SetSort) ]

Page 96: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

viewOptions : SearchOptions -> Html OptionsMsg

viewOptions options = input [] [ value options.sort, onInput SetSort ]

Page 97: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

viewOptions : SearchOptions -> Html OptionsMsg

view : Model -> Html Msgview model = div [ class "content" ] [ input [ defaultValue model.query, onInput SetQuery ] [] , button [ onClick Search ] [ text "Search" ] ]

Page 98: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

viewOptions : SearchOptions -> Html OptionsMsg

view : Model -> Html Msgview model = div [ class "content" ] [ input [ defaultValue model.query, onInput SetQuery ] [] , button [ onClick Search ] [ text "Search" ] ]

Page 99: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

view : Model -> Html Msgview model = div [ class "content" ] [ input [ defaultValue model.query, onInput SetQuery ] [] , button [ onClick Search ] [ text "Search" ] ]

viewOptions : SearchOptions -> Html OptionsMsg

Page 100: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

view : Model -> Html Msgview model = div [ class "content" ] [ input [ defaultValue model.query, onInput SetQuery ] [] , button [ onClick Search ] [ text "Search" ] ]

List StringList Int

viewOptions : SearchOptions -> Html OptionsMsg

Page 101: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

view : Model -> Html Msgview model = div [ class "content" ] [ input [ defaultValue model.query, onInput SetQuery ] [] , button [ onClick Search ] [ text "Search" ] ]

List StringList Int

List.map String.length foo

viewOptions : SearchOptions -> Html OptionsMsg

Page 102: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

view : Model -> Html Msgview model = div [ class "content" ] [ input [ defaultValue model.query, onInput SetQuery ] [] , button [ onClick Search ] [ text "Search" ] ]

List StringList Int

List.map String.length fooString.length : String -> Int

viewOptions : SearchOptions -> Html OptionsMsg

Page 103: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

view : Model -> Html Msgview model = div [ class "content" ] [ input [ defaultValue model.query, onInput SetQuery ] [] , button [ onClick Search ] [ text "Search" ] ]

Html StringHtml Int

Html.map String.length fooString.length : String -> Int

viewOptions : SearchOptions -> Html OptionsMsg

Page 104: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

view : Model -> Html Msgview model = div [ class "content" ] [ input [ defaultValue model.query, onInput SetQuery ] [] , button [ onClick Search ] [ text "Search" ] ]

Html StringHtml Int

Html.map String.length fooString.length : String -> Int

viewOptions : SearchOptions -> Html OptionsMsg

Page 105: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

Html OptionsMsg

Html Msg

Page 106: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

Html OptionsMsg Html.map

Html Msg

Page 107: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

Html OptionsMsg Html.map ???

Html Msg

Page 108: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

Html OptionsMsg OptionsMsg -> Msg Html.map ??? Html Msg

Page 109: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

type Msg = Search | SetQuery String | DeleteById Int | Options OptionsMsg

Html OptionsMsg OptionsMsg -> Msg Html.map ??? Html Msg

Page 110: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

type Msg = Search | SetQuery String | DeleteById Int | Options OptionsMsg

Html OptionsMsg OptionsMsg -> Msg Html.map ??? Html Msg

Page 111: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

viewOptions : SearchOptions -> Html OptionsMsg

view : Model -> Html Msgview model = div [ class "content" ] [ input [ defaultValue model.query, onInput SetQuery ] [] , button [ onClick Search ] [ text "Search" ] ]

Page 112: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

viewOptions : SearchOptions -> Html OptionsMsg

view : Model -> Html Msgview model = div [ class "content" ] [ input [ defaultValue model.query, onInput SetQuery ] [] , button [ onClick Search ] [ text "Search" ] , viewOptions model.options ]

Page 113: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

viewOptions : SearchOptions -> Html OptionsMsg

view : Model -> Html Msgview model = div [ class "content" ] [ input [ defaultValue model.query, onInput SetQuery ] [] , button [ onClick Search ] [ text "Search" ] , viewOptions model.options ]

Page 114: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

viewOptions : SearchOptions -> Html OptionsMsg

view : Model -> Html Msgview model = div [ class "content" ] [ input [ defaultValue model.query, onInput SetQuery ] [] , button [ onClick Search ] [ text "Search" ] , Html.map ??????? (viewOptions model.options) ]

Page 115: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

viewOptions : SearchOptions -> Html OptionsMsg

view : Model -> Html Msgview model = div [ class "content" ] [ input [ defaultValue model.query, onInput SetQuery ] [] , button [ onClick Search ] [ text "Search" ] , Html.map Options (viewOptions model.options) ]

type Msg = Search | SetQuery String | DeleteById Int | Options OptionsMsg

Page 116: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

viewOptions : SearchOptions -> Html OptionsMsg

view : Model -> Html Msgview model = div [ class "content" ] [ input [ defaultValue model.query, onInput SetQuery ] [] , button [ onClick Search ] [ text "Search" ] , Html.map Options (viewOptions model.options) ]

type Msg = Search | SetQuery String | DeleteById Int | Options OptionsMsg

Page 117: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

viewOptions : SearchOptions -> Html OptionsMsg

view : Model -> Html Msgview model = div [ class "content" ] [ input [ defaultValue model.query, onInput SetQuery ] [] , button [ onClick Search ] [ text "Search" ] , Html.map Options (viewOptions model.options) , ul [] (List.map viewSearchResult model.results) ]

Page 118: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

viewOptions : SearchOptions -> Html OptionsMsg

view : Model -> Html Msgview model = div [ class "content" ] [ input [ defaultValue model.query, onInput SetQuery ] [] , button [ onClick Search ] [ text "Search" ] , Html.map Options (viewOptions model.options) , ul [] (List.map viewSearchResult model.results) ]

viewSearchResult : SearchResult -> Html Msg

Page 119: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

viewOptions : SearchOptions -> Html OptionsMsg

view : Model -> Html Msgview model = div [ class "content" ] [ input [ defaultValue model.query, onInput SetQuery ] [] , button [ onClick Search ] [ text "Search" ] , Html.map Options (viewOptions model.options) , ul [] (List.map viewSearchResult model.results) ]

viewSearchResult : SearchResult -> Html Msg

Page 120: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

viewOptions : SearchOptions -> Html OptionsMsg

view : Model -> Html Msgview model = div [ class "content" ] [ input [ defaultValue model.query, onInput SetQuery ] [] , button [ onClick Search ] [ text "Search" ] , Html.map Options (viewOptions model.options) , ul [] (List.map viewSearchResult model.results) ]

viewSearchResult : SearchResult -> Html Msg

Page 121: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

viewOptions : SearchOptions -> Html OptionsMsg

view : Model -> Html Msgview model = div [ class "content" ] [ input [ defaultValue model.query, onInput SetQuery ] [] , button [ onClick Search ] [ text "Search" ] , Html.map Options (viewOptions model.options) , ul [] (List.map viewSearchResult model.results) ]

viewSearchResult : SearchResult -> Html Msg

Page 122: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

Recap

Page 123: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

type Msg = Search | SetQuery String | DeleteById Int | SetMinStars String | SetSearchIn String | SetUserFilter String

type alias Model = { query : String , results : List SearchResult , errorMessage : Maybe String , minStars : Int , minStarsError : Maybe String , searchIn : String , userFilter : String }

viewSearchResult : Model -> Html MsgviewSearchResult model = input [] [ value model.sort, onInput SetSort ]

Page 124: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

type Msg = Search | SetQuery String | DeleteById Int | Options OptionsMsg

type OptionsMsg = SetMinStars String | SetSearchIn String | SetUserFilter String

type alias Model = { query : String , results : List SearchResult , errorMessage : Maybe String , options : SearchOptions }

type alias SearchOptions = { minStars : Int , minStarsError : Maybe String , searchIn : String , userFilter : String }

viewSearchResult : Model -> Html MsgviewSearchResult model = input [] [ value model.options.sort, onInput (Options SetSort) ]

Page 125: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

type Msg = Search | SetQuery String | DeleteById Int | Options OptionsMsg

type OptionsMsg = SetMinStars String | SetSearchIn String | SetUserFilter String

type alias Model = { query : String , results : List SearchResult , errorMessage : Maybe String , options : SearchOptions }

type alias SearchOptions = { minStars : Int , minStarsError : Maybe String , searchIn : String , userFilter : String }

viewSearchResult : SearchOptions -> Html OptionsMsgviewSearchResult options = input [] [ value options.sort, onInput SetSort ]

Page 126: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

type Msg = Search | SetQuery String | DeleteById Int | Options OptionsMsg

type OptionsMsg = SetMinStars String | SetSearchIn String | SetUserFilter String

type alias Model = { query : String , results : List SearchResult , errorMessage : Maybe String , options : SearchOptions }

type alias SearchOptions = { minStars : Int , minStarsError : Maybe String , searchIn : String , userFilter : String }

viewSearchResult : SearchOptions -> Html OptionsMsgviewSearchResult options = input [] [ value options.sort, onInput SetSort ]

Html.map Options Html Msg

Page 127: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

other ways to map

Page 128: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

List.map : (originalVal -> newVal) -> List originalVal -> List newVal

Page 129: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

List.map : (originalVal -> newVal) -> List originalVal -> List newVal

Html.map : (originalMsg -> newMsg) -> Html originalMsg -> Html newMsg

Page 130: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

List.map : (originalVal -> newVal) -> List originalVal -> List newVal

Html.map : (originalMsg -> newMsg) -> Html originalMsg -> Html newMsg

Cmd.map : (originalMsg -> newMsg) -> Cmd originalMsg -> Cmd newMsg

Page 131: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

List.map : (originalVal -> newVal) -> List originalVal -> List newVal

Html.map : (originalMsg -> newMsg) -> Html originalMsg -> Html newMsg

Cmd.map : (originalMsg -> newMsg) -> Cmd originalMsg -> Cmd newMsg

Sub.map : (originalMsg -> newMsg) -> Sub originalMsg -> Sub newMsg

Page 132: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

List.map : (originalVal -> newVal) -> List originalVal -> List newVal

Html.map : (originalMsg -> newMsg) -> Html originalMsg -> Html newMsg

Cmd.map : (originalMsg -> newMsg) -> Cmd originalMsg -> Cmd newMsg

Sub.map : (originalMsg -> newMsg) -> Sub originalMsg -> Sub newMsg

delegation!

Page 133: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

viewOptions : SearchOptions -> Html OptionsMsg

view : Model -> Html Msgview model = div [] [ input [ defaultValue model.query, onInput SetQuery ] [] , Html.map Options (viewOptions model.options) ]

type Msg = Search | SetQuery String | DeleteById Int | Options OptionsMsg

Exercise: resolve the TODOs in part10type alias Model = { query : String , results : List SearchResult , options : SearchOptions }

Page 134: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

11. Scaling Elm Code

Page 135: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

The Deeply Nested Component Problem

Page 136: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

The Deeply Nested Component Problem

solving

Page 137: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

Component

Page 138: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

Web ComponentsReact Components

Angular ComponentsEmber ComponentsMithril ComponentsVue Components

Page 139: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

Componentowns its own state

Page 140: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

Header Componentowns its own state

Footer Componentowns its own state

Body Componentowns its own state

Page 141: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

owns its own state

owns its own state

owns its own state

owns its own state owns its own state owns its own stateowns its own state

owns its own state owns its own state

owns its own state

owns its own state

owns its own state owns its own state owns its own state owns its own state

Page 142: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

owns its own state

owns its own state

owns its own state

owns its own state owns its own state owns its own stateowns its own state

owns its own state owns its own state

owns its own state

owns its own state

owns its own state owns its own state owns its own state owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

Page 143: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

owns its own state

owns its own state

owns its own state

owns its own state owns its own state owns its own stateowns its own state

owns its own state owns its own state

owns its own state

owns its own state

owns its own state owns its own state owns its own state owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

deeply nested components

Page 144: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

owns its own state

owns its own state

owns its own state

owns its own state owns its own state owns its own stateowns its own state

owns its own state owns its own state

owns its own state

owns its own state

owns its own state owns its own state owns its own state choose language

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

new feature

Page 145: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

owns its own state

owns its own state

owns its own state

owns its own state owns its own state owns its own stateowns its own state

owns its own state owns its own state

owns its own state

owns its own state

owns its own state owns its own state owns its own state choose language

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

Page 146: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

owns its own state

owns its own state

owns its own state

owns its own state owns its own state owns its own stateowns its own state

owns its own state owns its own state

owns its own state

owns its own state

owns its own state owns its own state owns its own state choose language

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

Page 147: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

owns its own state

owns its own state

owns its own state

owns its own state owns its own state owns its own stateowns its own state

owns its own state owns its own state

owns its own state

owns its own state

owns its own state owns its own state owns its own state choose language

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

parent-child communication

Page 148: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

owns its own state

owns its own state

owns its own state

owns its own state owns its own state owns its own stateowns its own state

owns its own state owns its own state

owns its own state

owns its own state

owns its own state owns its own state owns its own state choose language

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

Page 149: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

owns its own state

owns its own state

owns its own state

owns its own state owns its own state owns its own stateowns its own state

owns its own state owns its own state

owns its own state

owns its own state

owns its own state owns its own state owns its own state choose language

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

Page 150: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

owns its own state

owns its own state

owns its own state

owns its own state owns its own state owns its own stateowns its own state

owns its own state owns its own state

owns its own state

owns its own state

owns its own state owns its own state owns its own state choose language

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

owns its own state

Page 151: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

The Deeply Nested Component Problem

Page 152: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

The Deeply Nested Component Problem

solving

Page 153: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

The Deeply Nested Component Problem

solving

unidirectional data flow

Page 154: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

The Deeply Nested Component Problem

solving

unidirectional data flow

Flux

Page 155: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

The Deeply Nested Component Problem

solving

unidirectional data flow

FluxRedux

Page 156: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

viewupdate Model

Elm Runtime

Page 157: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

viewupdate Model

Elm Runtime

unidirectional data flow

Page 158: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

viewupdate Model

Elm Runtime

The Elm Architecture

unidirectional data flow

Page 159: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

quick summary

Page 160: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

Nest stateful components to describe application

Page 161: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

The Deeply Nested Component Problem

Nest stateful components to describe application

Page 162: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

The Deeply Nested Component Problem

Unidirectional Data Flow

Nest stateful components to describe application

Page 163: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

The Deeply Nested Component Problem

Unidirectional Data Flow

Nest stateful components to describe application

Page 164: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

The Deeply Nested Component Problem

Nest stateful components to describe application

Unidirectional Data Flow

Page 165: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

is this a problem we're allowed to not have?

Page 166: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

is this a problem we're allowed to not have?

yes!

Page 167: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

45,000 lines of Production Elm Code

Page 168: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

45,000 lines of Production Elm Code

Page 169: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

45,000 lines of Production Elm Code

simpler

Page 170: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

45,000 lines of Production Elm Code

simpler

different

Page 171: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

how?

45,000 lines of Production Elm Code

Page 172: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

how do we keep code modular at scale?

45,000 lines of Production Elm Code

Page 173: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

how do we keep code modular at scale?

how do we share code without duplication?

45,000 lines of Production Elm Code

Page 174: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

viewupdate Model

Elm Runtime

specific techniques

Page 175: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

viewupdate Model

Elm Runtime

specific techniques

for scaling in a modular way

Page 176: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

viewupdate Model

Elm Runtime

specific techniques

for scaling in a modular way

for sharing code without duplication

Page 177: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

Scaling Fundamentals

1. Model2. view3. update

viewupdate Model

Elm Runtime

Page 178: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

Step 1: expandStep 2: refactor

Scaling Fundamentals

1. Model2. view3. update

Page 179: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

1. When view gets painfully large, subdivide it.

Page 180: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

Split it into smaller helper functions.

1. When view gets painfully large, subdivide it.

Page 181: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

Split it into smaller helper functions.

1. When view gets painfully large, subdivide it.

viewSearchResult : SearchResult -> Html Msg

viewErrorMessage : Maybe String -> Html msg

viewOptions : SearchOptions -> Html OptionsMsg

Page 182: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

Split it into smaller helper functions.

Don't change how update works!

Don't change how Model works!

1. When view gets painfully large, subdivide it.

Page 183: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

2. When Model gets painfully large, subdivide it.

Page 184: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

2. When Model gets painfully large, subdivide it.

Split out smaller pieces.

Page 185: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

2. When Model gets painfully large, subdivide it.

Split out smaller pieces.

type alias Model = { query : String , results : List SearchResult , errorMessage : Maybe String , options : SearchOptions }

Page 186: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

2. When Model gets painfully large, subdivide it.

Split out smaller pieces.

Don't change how view works!

Don't change how update works!

Page 187: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

3. When update gets painfully large, subdivide it.

Page 188: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

Split it into smaller helper functions.

3. When update gets painfully large, subdivide it.

Page 189: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

Split it into smaller helper functions.

3. When update gets painfully large, subdivide it.

updateOptions : OptionsMsg -> SearchOptions -> SearchOptions

type Msg = Search | Options OptionsMsg

Page 190: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

Split it into smaller helper functions.

Don't change how view works!

Don't change how Model works!

3. When update gets painfully large, subdivide it.

Page 191: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

Reusing Code without Duplication

Page 192: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

thinking in terms of functions

Page 193: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

thinking in terms of functionsnot components

Page 194: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

logo : Html msglogo = img [ src "logo.png" ] []

view : Model -> Html Msgview model = logo

Page 195: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

fancyLink : String -> String -> Html msgfancyLink url caption = a [ class "fancy-link", href url ] [ text caption ]

view : Model -> Html Msgview model = fancyLink "/about" "About Us"

Page 196: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

profile : User -> Html msgprofile user = div [ class "profile" ] [ a [ href ("/users/" ++ user.username) ] [ img [ class "user-photo", src user.photo ] [] ] ]

view : Model -> Html Msgview model = profile model.currentUser

Page 197: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

checkbox : String -> Bool -> Html msgcheckbox caption isChecked = label [ input [ type' "checkbox" , checked isChecked ] , text caption ]

view : Model -> Html Msgview model = checkbox "enable sounds" model.enableSounds

Page 198: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

checkbox : msg -> String -> Bool -> Html msgcheckbox toggleChecked caption isChecked = label [ input [ type' "checkbox" , checked isChecked , onClick toggleChecked ] , text caption ]

view : Model -> Html Msgview model = checkbox ToggleSounds "enable sounds" model.enableSounds

Page 199: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

dropdown : List String -> String -> Html msgdropdown options selectedOpt = let viewOpt opt = option [ selected (opt == selectedOpt) ] [ text opt ] in select [] (List.map viewOpt options)

view : Model -> Html Msgview model = dropdown [ "cat", "dog", "orangutan" ] "cat"

Page 200: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

dropdown : (String -> msg) -> List String -> String -> Html msgdropdown selectOpt options selectedOpt = let viewOpt opt = option [ selected (opt == selectedOpt) ] [ text opt ] in select [ onChange selectOpt ] (List.map viewOpt options)

view : Model -> Html Msgview model = dropdown ChooseSpiritAnimal [ "cat", "dog", "orangutan" ] "cat"

Page 201: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

portable signup form

Page 202: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

signup : { setUsername : (String -> msg) , setPassword : (String -> msg) , setFirstName : (String -> msg) , setLastName : (String -> msg) , setEmail : (String -> msg) , cancel : msg , submit : (List ValidationError -> msg) } -> { username : String , password : String , firstName : String , lastName : String , email : String } -> Html msg

Page 203: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

view : SignupState -> Html SignupMsg

Page 204: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

view : SignupState -> Html SignupMsg

update : SignupMsg -> SignupModel -> ( SignupModel, Cmd SignupMsg )

Page 205: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

view : SignupState -> Html SignupMsg

update : SignupMsg -> SignupModel -> ( SignupModel, Cmd SignupMsg )

init : ( SignupModel, SignupMsg )

Page 206: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

type alias Model = { signup : SignupModel , … }

view : Model -> Html Msgview model = Signup.view model.signup |> Html.map ...

view : SignupState -> Html SignupMsg

update : SignupMsg -> SignupModel -> ( SignupModel, Cmd SignupMsg )

init : ( SignupModel, SignupMsg )

Page 207: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

view : SignupState -> Html SignupMsg

update : SignupMsg -> SignupModel -> ( SignupModel, Cmd SignupMsg )

init : ( SignupModel, SignupMsg )

type alias Model = { signup : SignupModel , … }

view : Model -> Html Msgview model = Signup.view model.signup |> Html.map ...

type Msg = SignupMsg SignupMsg | OtherStuff

update : Msg -> Model -> ( Model, Cmd Msg)update msg model = case msg of SignupMsg signupMsg -> ….

Page 208: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

An Easy Mistake to Make

Page 209: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

An Easy Mistake to Make

MVU lets me isolate state...

Page 210: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

An Easy Mistake to Make

MVU lets me isolate state...nesting isolated state feels familiar...

Page 211: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

!!!

An Easy Mistake to Make

MVU lets me isolate state...nesting isolated state feels familiar...

Page 212: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

An Easy Mistake to Make

MVU lets me isolate state...nesting isolated state feels familiar...

Page 213: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

sortable table

Page 214: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

Exercise: resolve the TODOs in part11

type alias Model = { signup : SignupModel , … }

view : Model -> Html Msgview model = Signup.view model.signup |> Html.map ...

type Msg = SignupMsg SignupMsg | OtherStuff

update : Msg -> Model -> ( Model, Cmd Msg)update msg model = case msg of SignupMsg signupMsg -> ….

Page 215: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

12. Performance Optimization

Page 216: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

Collections Performance

Page 217: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

5 :: []

Page 218: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

5 :: []

== [ 5 ]

Page 219: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

1 :: (5 :: [])

Page 220: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

1 :: (5 :: [])

== [ 1, 5 ]

Page 221: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

4 :: (1 :: (5 :: []))

Page 222: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

4 :: (1 :: (5 :: []))

== [ 4, 1, 5 ]

Page 223: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

4 :: (1 :: (5 :: []))

== [ 4, 1, 5 ]

adding to the front: cheap!

Page 224: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

4 :: (1 :: (5 :: []))

== [ 4, 1, 5 ]

adding to the front: cheap!

adding to the back: expensive!

Page 225: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

4 :: (1 :: (5 :: []))

== [ 4, 1, 5 ]

adding to the front: cheap!

adding to the back: expensive!

reading the first element: cheap!

Page 226: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

4 :: (1 :: (5 :: []))

== [ 4, 1, 5 ]

adding to the front: cheap!

adding to the back: expensive!

reading the first element: cheap!reading other elements: expensive!

Page 227: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

case myList of [] -> -- some logic goes here

4 :: (1 :: (5 :: []))== [ 4, 1, 5 ]

Page 228: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

case myList of [] -> -- some logic goes here

first :: rest -> -- some logic goes here

4 :: (1 :: (5 :: []))== [ 4, 1, 5 ]

Page 229: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

case myList of [] -> -- some logic goes here

first :: rest -> -- some logic goes here

4 :: (1 :: (5 :: []))== [ 4, 1, 5 ]

Page 230: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

case myList of [] -> -- some logic goes here

first :: rest -> -- some logic goes here

4 :: (1 :: (5 :: []))== [ 4, 1, 5 ]

Page 231: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

case myList of [] -> -- some logic goes here

singleton :: [] -> -- some logic goes here

first :: rest -> -- some logic goes here

4 :: (1 :: (5 :: []))== [ 4, 1, 5 ]

Page 232: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

countEmptyStrings : List String -> Int

Page 233: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

countEmptyStrings : List String -> IntcountEmptyStrings list = case list of [] -> 0

Page 234: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

countEmptyStrings : List String -> IntcountEmptyStrings list = case list of [] -> 0

first :: rest ->

Page 235: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

countEmptyStrings : List String -> IntcountEmptyStrings list = case list of [] -> 0

first :: rest -> if first == "" then 1 + (countEmptyStrings rest)

Page 236: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

countEmptyStrings : List String -> IntcountEmptyStrings list = case list of [] -> 0

first :: rest -> if first == "" then 1 + (countEmptyStrings rest) else countEmptyStrings rest

Page 237: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

countEmptyStrings : List String -> IntcountEmptyStrings list = case list of [] -> 0

first :: rest -> if first == "" then 1 + (countEmptyStrings rest) else countEmptyStrings rest

recurse, then immediately return

Page 238: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

countEmptyStrings : List String -> IntcountEmptyStrings list = case list of [] -> 0

first :: rest -> if first == "" then 1 + (countEmptyStrings rest) else countEmptyStrings rest

recurse, then immediately return: tail call!

Page 239: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

countEmptyStrings : List String -> IntcountEmptyStrings list = case list of [] -> 0

first :: rest -> if first == "" then 1 + (countEmptyStrings rest) else countEmptyStrings rest

recurse, then do something else before returning: not tail call

Page 240: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

countEmptyStrings : List String -> IntcountEmptyStrings list = case list of [] -> 0

first :: rest -> if first == "" then 1 + (countEmptyStrings rest) else countEmptyStrings rest

Page 241: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

myArray : Array FloatmyArray = Array.fromList [ 1.1, 2.2, 3.3 ]

Page 242: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

myArray : Array FloatmyArray = Array.fromList [ 1.1, 2.2, 3.3 ]

adding to the front: less cheap

adding to the back: less expensive

Page 243: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

myArray : Array FloatmyArray = Array.fromList [ 1.1, 2.2, 3.3 ]

adding to the front: less cheap

adding to the back: less expensive

reading any element: cheap!removing first element: expensive!

Page 244: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

flavors : Dict String Intflavors = Dict.fromList [ ( "vanilla", 5 ) , ( "chocolate", 9 ) , ( "strawberry", 7 ) ]

Page 245: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

Dict.get "strawberry" flavors

flavors : Dict String Intflavors = Dict.fromList [ ( "vanilla", 5 ) , ( "chocolate", 9 ) , ( "strawberry", 7 ) ]

Page 246: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

Dict.get "strawberry" flavors == Just 7

flavors : Dict String Intflavors = Dict.fromList [ ( "vanilla", 5 ) , ( "chocolate", 9 ) , ( "strawberry", 7 ) ]

Page 247: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

Dict.remove "strawberry" flavors == Dict.fromList [ ( "vanilla", 5 ) , ( "chocolate", 9 ) ]

flavors : Dict String Intflavors = Dict.fromList [ ( "vanilla", 5 ) , ( "chocolate", 9 ) , ( "strawberry", 7 ) ]

Page 248: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

div [ class "flavor-list" ] flavors

flavors : Dict String Intflavors = Dict.fromList [ ( "vanilla", 5 ) , ( "chocolate", 9 ) , ( "strawberry", 7 ) ]

Page 249: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

div [ class "flavor-list" ] flavors

flavors : Dict String Intflavors = Dict.fromList [ ( "vanilla", 5 ) , ( "chocolate", 9 ) , ( "strawberry", 7 ) ]

Page 250: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

Rendering from a Dict

Page 251: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

Dict.values

Page 252: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

List.sortBy

Dict.values

Page 253: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

Skipping Virtual DOM building

Page 254: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

viewMenu : List MenuItem -> Html MsgviewMenu items = -- lots of view code goes here

Page 255: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

viewMenu : List MenuItem -> Html MsgviewMenu items = -- lots of view code goes here

view : Model -> Html Msgview model = -- lots of other code goes here...

viewMenu model.menuItems

Page 256: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

viewMenu : List MenuItem -> Html MsgviewMenu items = -- lots of view code goes here

view : Model -> Html Msgview model = -- lots of other code goes here...

lazy viewMenu model.menuItems

Page 257: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

viewMenu : Config -> List MenuItem -> Html MsgviewMenu config items = -- lots of view code goes here

view : Model -> Html Msgview model = -- lots of other code goes here...

lazy2 viewMenu model.config model.menuItems

Page 258: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

Debug.log

Page 259: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

Debug.log "some numbers" [ 1, 2, 3 ]

Page 260: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

someNumbers = Debug.log "some numbers" [ 1, 2, 3 ]

Page 261: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

someNumbers = [ 1, 2, 3 ]

Debug.log "some numbers"

Page 262: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

requestAnimationFrame

Page 263: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

viewupdate Model

Elm Runtime

Page 264: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

viewupdate Model

Elm Runtime

browser repaints at ~60fps

Page 265: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

viewupdate Model

Elm Runtime

browser repaints at ~60fps

computing virtual DOM more often than that is a waste!

Page 266: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

viewupdate Model

Elm Runtime

browser repaints at ~60fps

computing virtual DOM more often than that is a waste!

keep updating model and running commands

Page 267: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

viewupdate Model

Elm Runtime

browser repaints at ~60fps

computing virtual DOM more often than that is a waste!

keep updating model and running commandsdon't bother running view until the next repaint

Page 268: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

viewupdate Model

Elm Runtime

keep updating model and running commandsdon't bother running view until the next repaint

how do we get this?

Page 269: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

viewupdate Model

Elm Runtime

keep updating model and running commandsdon't bother running view until the next repaint

This is just how Elm rolls.

Page 270: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

don't count on Debug.log in views!

Page 271: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

Exercise: resolve the TODOs in part13

lazy

Debug.log "foo is" foo

Page 272: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

13. Tools

Page 273: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

HTML-to-Elm

Page 274: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

JSON-to-Elm

sample JSON

Page 275: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

Error Message Catalog

Page 276: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

create-elm-app

Page 277: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

elm-format

Page 278: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

elm-reactor

Page 279: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

elm-css

Page 280: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

Built With Elm: builtwithelm.co

Links of Interest

Elm Community: elm-community.org

NRI Tech Blog: tech.noredink.com

Page 281: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

Exercise: resolve the TODO in ElmHubCss.elm

package.elm-lang.org/packages/rtfeldman/elm-css/latest

Page 282: @rtfeldman - Frontend Masters · reverse : List val -> List val reverse : List thing -> List thing reverse : List a -> List a

Implement additional search options:

ElmHub Hacking!

https://developer.github.com/v3/search/#search-repositories

Refactor to results : Dict Int SearchResult

Move SearchOptions into its own module

Migrate tests from part9 to part14 and add tests for update