Reusable views
Problem
Solution
Main.elm
type alias ButtonModel =
{ text : String
}
​
type alias Model =
{ button: ButtonModel
}
​
type ButtonMsg =
ButtonPressed
​
type Msg =
ButtonSpecific ButtonMsg
| Reset
​
update : Msg -> Model -> (Model,Cmd Msg)
update msg ({button} as model) =
case msg of
ButtonSpecific ButtonPressed ->
( { model
| button =
{ button
| text = "Thanks!"
}
}
, Cmd.none
)
_ ->
(model, Cmd.none)
​
{-|
This can be moved into a seperate file as it still
depends on Msg.
-}
myButton : ButtonModel -> List (Attribute Msg) -> List (Html Msg) -> Html Msg
myButton {text} attributes children =
Html.div []
(Html.button
[ (Events.onClick <| ButtonSpecific ButtonPressed)
:: attributes
]
[ Html.text text
]
)
:: children
​
view : Model -> Html Msg
view model =
Html.div []
[ Html.h1 []
[ Html.text "Here is a reusable view for a button"
]
, myButton []
[ Html.text "Click me!"
]
]
Main.elm
import MyButton
​
type alias Model =
{ button: MyButton.Model
}
​
type Msg =
| ButtonPressed String
| Reset
​
update : Msg -> Model -> (Model,Cmd Msg)
update msg ({button} as model) =
case msg of
ButtonPressed string ->
( button |> MyButton.buttonPressed string
, cmd
)
_ ->
(model, Cmd.none)
​
view : Model -> Html Msg
view ({button} as model) =
Html.div []
[ Html.h1 []
[ Html.text "Here is a reusable view for a button"
]
, MyButton.view ButtonPressed
button
[]
[ Html.text "Click me!"
]
]
MyButton.elm
type alias Model =
{ text : String
}
​
buttonPressed : String -> Model -> Model
buttonPressed string button =
{ button
| text = string
}
​
view : (string -> msg) -> ButtonModel -> List (Attribute msg) -> List (Html msg) -> Html msg
view onClick {text} attributes children =
Html.div []
(Html.button
[ (Events.onClick <| onClick <| "Thanks!")
:: attributes
]
[ Html.text text
]
)
:: children

Question

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

Answer

The trick is to pass the Messages along.

Further reading

Copy link
On this page
Question
Answer
Further reading