I am creating a small view component that is composed of a number of optional Maybe String s (as arguments to Html.text ) interspersed with other Html Msg s.
My current solution is a bit unwieldy and I’m sure it could be handled more idiomatically. I’m using a number of nested case statements to decided what to show. I think a combination of Maybe.map s and Maybe.andThen s could work here but I can’t quite figure it out.
My current solution:
type alias Model =
{ subcomponentOne : Maybe SubcomponentOne
, subcomponentTwo : Maybe SubcomponentTwo
, modelString : Maybe String
}
type alias SubcomponentOne =
{ subcomponentOneString : String
}
type alias SubcomponentTwo =
{ subcomponentTwoString : String
}
componentView : Model -> Html Msg
componentView model =
case model.subcomponentOne of
Nothing ->
text ""
Just subcomponentOne ->
case model.modelString of
Nothing ->
div [] [ Html.strong [] [ text subcomponentOne.subcomponentOneString ] ]
Just modelString ->
case model.subcomponentTwo of
Nothing ->
div [] [ Html.strong [] [ text subcomponentOne.subcomponentOneString ], br [] [], text modelString ]
Just subcomponentTwo ->
div [] [ Html.strong [] [ text subcomponentOne.subcomponentOneString ], br [] [], text (modelString ++ " - " ++ subcomponentTwo.subcomponentTwoString) ]
componentView : Model -> Html Msg
componentView model =
case ( model.subcomponentOne, model.modelString, model.subcomponentTwo ) of
( Nothing, _, _ ) ->
text ""
( Just subcomponentOne, Nothing, _ ) ->
div [] [ Html.strong [] [ text subcomponentOne.subcomponentOneString ] ]
( Just subcomponentOne, Just modelString, Nothing ) ->
div [] [ Html.strong [] [ text subcomponentOne.subcomponentOneString ], br [] [], text modelString ]
( Just subcomponentOne, Just modelString, Just subcomponentTwo ) ->
div [] [ Html.strong [] [ text subcomponentOne.subcomponentOneString ], br [] [], text (modelString ++ " - " ++ subcomponentTwo.subcomponentTwoString) ]
I tried a Maybe.map version but it looks worse.
componentView : Model -> Html Msg
componentView model =
let
viewModelString modelString =
[ br [] []
, case model.subcomponentTwo of
Nothing ->
text modelString
Just subcomponentTwo ->
text (modelString ++ " - " ++ subcomponentTwo.subcomponentTwoString)
]
viewSubOne subcomponentOne =
Html.strong [] [ text subcomponentOne.subcomponentOneString ]
:: Maybe.map viewModelString model
|> Maybe.withDefault []
|> List.concat
|> div []
in
Maybe.map viewSubOne model.subcomponentOne
|> Maybe.withDefault (text "")