Elm 如何将Html.Html msg转换为Html.Html msg?
我正试图用Elm编写一个TabControl,如下所示Elm 如何将Html.Html msg转换为Html.Html msg?,elm,Elm,我正试图用Elm编写一个TabControl,如下所示 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) , s
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 ""
这是由
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
,那么
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
如果我没有那么做
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 Msg,那么
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 msg
和Html.Html msg
啊。。所以我可以映射value.content以返回类似这样的消息
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 ""
啊。。所以我可以映射value.content以返回类似这样的消息
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 ""
如果你想公开你的
Msg
类型,你需要模块的用户提供一个函数,将你的Msg
翻译成他们的Msg
因此,如果顶级Msg
类型如下所示:
type Msg
= NoOp
| TabControlMsg TabControl.Msg
| SomethingElse
然后render可以接受一个函数,该函数接受一个TabControl.Msg
,并返回一个Msg
,在本例中,该函数将是TabControlMsg
构造函数
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
]
然后调整模块中的代码以使用该功能:
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 ""
如果你想公开你的
Msg
类型,你需要模块的用户提供一个函数,将你的Msg
翻译成他们的Msg
因此,如果顶级Msg
类型如下所示:
type Msg
= NoOp
| TabControlMsg TabControl.Msg
| SomethingElse
然后render可以接受一个函数,该函数接受一个TabControl.Msg
,并返回一个Msg
,在本例中,该函数将是TabControlMsg
构造函数
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
]
然后调整模块中的代码以使用该功能:
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 ""