首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何将Html.Html消息转换为Html.Html消息?

如何将Html.Html消息转换为Html.Html消息?
EN

Stack Overflow用户
提问于 2020-12-19 04:01:11
回答 2查看 146关注 0票数 1

我正在尝试用Elm编写一个TabControl,如下所示

代码语言:javascript
运行
复制
module TabControl exposing (..)

import Html 
import Html.Attributes as Attributes
import Html.Events
import Array

type Msg
    = OnSelectedTabChanged
    | NoOp

type alias Model msg =
    { tabs : List (Tab msg)
    , selectedIndex : Int    
    }

constructor : Model msg
constructor =
    { tabs = []
    , selectedIndex = 0
    }

type alias Tab msg =
    { title : String
    , content : Html.Html msg 
    }

withTab : Tab msg -> Model msg -> (Model msg)
withTab tab model = 
    { model | tabs = model.tabs ++ [tab] }

render : Model msg -> Html.Html msg
render model =
    let 
        header = renderTabHeaders model
        content = renderSelectedTabContent model
    in
    Html.div [] [ header, content ]

renderTabHeaders : Model msg -> Html.Html msg
renderTabHeaders model =
    Html.div []    
    [
        Html.ul []        
        (
            model.tabs 
                |> List.map (\(tab) -> renderTabHeader tab)           
        )
    ]

renderTabHeader : Tab msg -> Html.Html msg
renderTabHeader tab =
    Html.li [Html.Events.onClick OnSelectedTabChanged] [Html.text tab.title]                        

renderSelectedTabContent : Model msg -> Html.Html msg
renderSelectedTabContent model =
    let 
        array = 
            Array.fromList model.tabs

        item = 
            Array.get model.selectedIndex array
    in
        case item of 
            Just value ->
                value.content
            Nothing ->
                Html.text ""

,它是由

代码语言:javascript
运行
复制
module Main exposing (..)

import Browser
import Html exposing (Html, button, div, text)
import Html.Events exposing (onClick)
import TabControl

main =
  Browser.sandbox { init = 0, update = update, view = view }

view model =
  div []  
  [  
    TabControl.constructor
    |> TabControl.withTab (TabControl.Tab "title 1" (Html.text "html 1"))
    |> TabControl.withTab (TabControl.Tab "title 2" (Html.text "html 2"))
    |> TabControl.render
  ]

然而,我似乎不能得到正确的返回类型。

如果我将renderTabHeader : Tab msg -> Html.Html msg重构为renderTabHeader : Tab msg -> Html.Html Msg,那么

代码语言:javascript
运行
复制
Something is off with the body of the `renderTabHeaders` definition:

This `div` call produces:

    Html.Html Msg

But the type annotation on `renderTabHeaders` says it should be:

    Html.Html msg

如果我不这样做的话

代码语言:javascript
运行
复制
Something is off with the body of the `renderTabHeader` definition:

This `li` call produces:

    Html.Html Msg

But the type annotation on `renderTabHeader` says it should be:

    Html.Html msg

如果我让每个函数都返回Html.Html消息,那么

代码语言:javascript
运行
复制
Something is off with the 1st branch of this `case` expression:

67|                 value.content
                    ^^^^^^^^^^^^^
The value at .content is a:

    Html.Html msg

But the type annotation on `renderSelectedTabContent` says it should be:

    Html.Html Msg

我怎么可能在一个div中有元素,其中一些返回Html.Html msg,另一些返回Html.Html Msg?或者,如何在Html.Html msgHtml.Html Msg之间进行转换

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-12-19 06:00:30

如果你想公开你的Msg类型,你需要你的模块的用户提供一个将你的Msg转换成他们的msg的函数。

因此,如果顶级Msg类型如下所示:

代码语言:javascript
运行
复制
type Msg
    = NoOp
    | TabControlMsg TabControl.Msg
    | SomethingElse

然后,render可以接受一个函数,该函数接受一个TabControl.Msg并返回一个Msg,在本例中,它就是TabControlMsg构造函数。

代码语言:javascript
运行
复制
view model =
  div []  
  [  
    TabControl.constructor
    |> TabControl.withTab (TabControl.Tab "title 1" (Html.text "html 1"))
    |> TabControl.withTab (TabControl.Tab "title 2" (Html.text "html 2"))
    |> TabControl.render TabControlMsg
  ]

然后,您可以调整模块中的代码以使用该函数:

代码语言:javascript
运行
复制
render : (Msg -> msg) -> Model msg -> Html.Html msg
render toMsg model =
    let 
        header = renderTabHeaders model
        content = renderSelectedTabContent toMsg model
    in
    Html.div [] [ header, content ]

renderSelectedTabContent : (Msg -> msg) -> Model msg -> Html.Html msg
renderSelectedTabContent toMsg model =
    let 
        array = 
            Array.fromList model.tabs

        item = 
            Array.get model.selectedIndex array
    in
        case item of 
            Just value ->
                Html.map toMsg value.content
            Nothing ->
                Html.text ""
票数 4
EN

Stack Overflow用户

发布于 2020-12-19 04:29:39

啊.。因此,我可以像这样映射value.content以返回一个消息

代码语言:javascript
运行
复制
renderSelectedTabContent : Model msg -> Html.Html Msg
renderSelectedTabContent model =
    let 
        array = 
            Array.fromList model.tabs

        item = 
            Array.get model.selectedIndex array
    in
        case item of 
            Just value ->
                Html.map (\_ -> NoOp) value.content
            Nothing ->
                Html.text ""
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65363242

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档