Reusable views
Problem
Solution
Main.elm
1
type alias ButtonModel =
2
{ text : String
3
}
4
​
5
type alias Model =
6
{ button: ButtonModel
7
}
8
​
9
type ButtonMsg =
10
ButtonPressed
11
​
12
type Msg =
13
ButtonSpecific ButtonMsg
14
| Reset
15
​
16
update : Msg -> Model -> (Model,Cmd Msg)
17
update msg ({button} as model) =
18
case msg of
19
ButtonSpecific ButtonPressed ->
20
( { model
21
| button =
22
{ button
23
| text = "Thanks!"
24
}
25
}
26
, Cmd.none
27
)
28
_ ->
29
(model, Cmd.none)
30
​
31
{-|
32
This can be moved into a seperate file as it still
33
depends on Msg.
34
-}
35
myButton : ButtonModel -> List (Attribute Msg) -> List (Html Msg) -> Html Msg
36
myButton {text} attributes children =
37
Html.div []
38
(Html.button
39
[ (Events.onClick <| ButtonSpecific ButtonPressed)
40
:: attributes
41
]
42
[ Html.text text
43
]
44
)
45
:: children
46
​
47
view : Model -> Html Msg
48
view model =
49
Html.div []
50
[ Html.h1 []
51
[ Html.text "Here is a reusable view for a button"
52
]
53
, myButton []
54
[ Html.text "Click me!"
55
]
56
]
Copied!
Main.elm
1
import MyButton
2
​
3
type alias Model =
4
{ button: MyButton.Model
5
}
6
​
7
type Msg =
8
| ButtonPressed String
9
| Reset
10
​
11
update : Msg -> Model -> (Model,Cmd Msg)
12
update msg ({button} as model) =
13
case msg of
14
ButtonPressed string ->
15
( button |> MyButton.buttonPressed string
16
, cmd
17
)
18
_ ->
19
(model, Cmd.none)
20
​
21
view : Model -> Html Msg
22
view ({button} as model) =
23
Html.div []
24
[ Html.h1 []
25
[ Html.text "Here is a reusable view for a button"
26
]
27
, MyButton.view ButtonPressed
28
button
29
[]
30
[ Html.text "Click me!"
31
]
32
]
Copied!
MyButton.elm
1
type alias Model =
2
{ text : String
3
}
4
​
5
buttonPressed : String -> Model -> Model
6
buttonPressed string button =
7
{ button
8
| text = string
9
}
10
​
11
view : (string -> msg) -> ButtonModel -> List (Attribute msg) -> List (Html msg) -> Html msg
12
view onClick {text} attributes children =
13
Html.div []
14
(Html.button
15
[ (Events.onClick <| onClick <| "Thanks!")
16
:: attributes
17
]
18
[ Html.text text
19
]
20
)
21
:: children
Copied!

Question

How can I build a reusable view function with its own model?

Answer

The trick is to pass the Messages along.

Further reading