I like the Context record pattern. It's simple and can be extended.
You can start with a context record and, if the view gets more general purpose you can slowly move to a signature similar to those found in Html components where you would make its fields optional.
type alias Context msg =
{ someValue : String
, onMsg1 : Maybe msg
, onMsg2 : Maybe msg
}
defaultContext =
{ someValue = ""
, onMsg1 = Nothing
, onMsg2 = Nothing
}
type alias Attribute msg =
Context msg -> Context msg
someValue : String -> Attribute msg
someValue value ctx =
{ ctx | someValue = value }
onMsg1 : msg -> Attribute msg
onMsg1 msg ctx =
{ ctx | onMsg1 = msg }
onMsg2 : msg -> Attribute msg
onMsg2 msg ctx =
{ ctx | onMsg2 = msg }
view : List (Attribute msg) -> List (Html msg) -> Html msg
view props children =
let
ctx =
List.foldl (\p acc -> p acc) defaultContext props
content =
div [] [text ctx.someValue]
in
div []
[ content
, div [] children
]