如何将来自不同 elm 功能的多种 msg 类型集成到顶级应用程序中

fra*_*ure 1 elm

我有一个功能叫做Editor我正在尝试插入我的应用程序。它的视图返回一个类型Html EditorMsg。我把它插在这里:

edit : Editor.Types.Model -> Html EditorMsg
edit editorModel =
    div [ class "edit" ] [ Editor.view editorModel ]
Run Code Online (Sandbox Code Playgroud)

在应用程序中,我有路由,因此edit通过我的主view函数调用,加上几个管理要显示的路由的函数:

-- VIEW


view : Model -> Html Msg
view model =
    div []
        [ RoutingMsg navBar
        , EditorMsg (render model)
        ]


render : Model -> Html EditorMsg
render model =
    case model.route of
        Nothing ->
            li [] [ text "Invalid URL" ]

        Just route ->
            showRoute route model


showRoute : Route -> Model -> Html EditorMsg
showRoute route model =
    case route of
        Home ->
            home

        Editor ->
            edit model.editor
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,我的view也包含一个navBar,它返回 Html 可能包含不同类型的消息,RoutingMsg

navBar : Html RoutingMsg
navBar =
    NavBarState.config
        |> NavBarState.items
            [ navItem "/" "Home" False
            , navItem "/editor" "Edit" False
            ]
        |> NavBar.view
Run Code Online (Sandbox Code Playgroud)

这个设置没有编译,因为view我有一个包含两种不同类型的列表,一个返回Html RoutingMsg,另一个Html EditorMsg,所以我设置了一个联合类型来尝试包含这种差异:

type Msg
    = RoutingMsg (Html RoutingMsg)
    | EditorMsg (Html EditorMsg)
Run Code Online (Sandbox Code Playgroud)

这似乎有效,但后来我在我的更新方法中遇到了麻烦,匹配不太有效。总而言之,感觉好像我刚刚弄错了模式。我的目标是让我Editor有点独立,就像一个模块,可以插入不同的地方。但是我很难理解在 Elm 中,如何整合事物。

为了更简单地说明问题,我在 ellie-app 上创建了这个示例,它近似于我尝试做但无法正常工作的内容:https : //ellie-app.com/PKmzsV3PC7a1/1

我这里的方法是否不正确,或者如果不正确,我怎样才能让这段代码工作?

hal*_*bra 5

您应该使用Html.map将子消息映射到顶级Msg

这是你一直缺少的:

view : Model -> Html Msg
view model =
    div []
        [ Html.map ButtonDecMsg buttonDec
        , div [] [ text (toString model) ]
        , Html.map ButtonIncMsg buttonInc
        ]
Run Code Online (Sandbox Code Playgroud)

此外,子更新函数的类型注释定义应包括消息类型:

buttonDecUpdate : ButtonDecMsg -> Model -> Int
buttonDecUpdate msg model =
    model - 1
Run Code Online (Sandbox Code Playgroud)

这是一个工作应用程序的例子:https : //ellie-app.com/PM4H2dpFsfa1/0