如何将 Html.Html msg 转换为 Html.Html Msg?
How to convert Html.Html msg to Html.Html Msg?
我正尝试在 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)
, 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
]
但是,我似乎无法正确输入 return 类型。
如果我将 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
如果我让每一个函数 return Html.Html Msg then
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 中包含元素,其中一些元素 return Html.Html msg
一些元素 return Html.Html Msg
?或者,我如何在 Html.Html msg
和 Html.Html Msg
之间转换
啊..所以我可以将 value.content 映射到 return 像这样的 Msg
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
和 returns 和 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 ""
我正尝试在 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)
, 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
]
但是,我似乎无法正确输入 return 类型。
如果我将 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
如果我让每一个函数 return Html.Html Msg then
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 中包含元素,其中一些元素 return Html.Html msg
一些元素 return Html.Html Msg
?或者,我如何在 Html.Html msg
和 Html.Html Msg
啊..所以我可以将 value.content 映射到 return 像这样的 Msg
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
和 returns 和 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 ""