我无法在网上任何地方找到一个回答问题的例子:父组件如何响应来自子模块的不同操作? 考虑使用提交按钮的简单聊天消息输入:
//子组件:带提交按钮的文本输入
type Action
= InputChanged String
| MessageSent String
view : Signal.Address Action -> Model -> Html
view addr model =
div []
[ input
[ type' "text"
, value model.content
, on "input" targetValue (\val -> Signal.message addr (InputChanged val))
]
[]
, button
[ type' "submit"
, onClick addr (MessageSent model.content)
]
[ text "Send" ]
]
保留在此输入框中的父组件如何响应可能来自该输入框的两个操作?传统的"只是通过"看起来像这样:
//父组件,保留在帖子列表和子组件
中-- update
type Action
= MessageBoxAction MessageBox.Action
update : Action -> Model -> Model
update act model =
case act of
MessageBoxAction msg ->
{ model |
currentMessage = MessageBox.update msg model.currentMessage
}
-- view
view : Signal.Address Action -> Model -> Html
view addr model =
div []
[ MessageBox.view (Signal.forwardTo addr MessageBoxAction) model.currentMessage ]
我希望能够捕获来自该子组件的消息,并在正常情况下对其做出响应"只是通过"。像这样:
case act of
MessageBoxSubmit msg ->
let updatedMessage = MessageBox.update msg model.currentMessage
newPost = Posts.update msg model.posts
in
{ model |
posts = model.posts :: [ newPost ]
, currentMessage = updatedMessage
}
但我不知道如何做到这一点,特别是因为在将地址转发给孩子时,并不是说你有机会提供多个地址......
MessageBox.view (Signal.forwardTo addr MessageBoxAction) model.currentMessage
答案 0 :(得分:1)
有两条主要路线可以做到这一点。
您可以更改MessageBox update
的签名,以返回您向MessageBox init
提供的父操作。
init : (String -> parentAction) -> Model
init onSend =
{ onSend = onSend
, content = ""
}
update : Action -> Model -> (Model, Maybe parentAction)
update action model =
case action of
MessageSent msg ->
let
model' = ...
in
(model', Just (model.onSend msg))
InputChanged str ->
let
model' = ...
in
(model', Nothing)
并在父模块中执行:
init =
{ posts = []
, currentMessage = MessageBox.init HandleSent
}
update : Action -> Model -> Model
update act model =
case act of
MessageBoxAction msg ->
let
(currentMessage', send) = MessageBox.update msg model.currentMessage
model' = {model | currentMessage = currentMessage'}
in
case send of
Nothing -> model'
Just act -> update act model' -- you recursively call the update function with the new action that you received from the MessageBox.update
HandleSent str -> { model | posts = str::model.posts }
sentMessage action =
case action of
MessageSent msg -> Just msg
_ -> Nothing
在父母中
update : Action -> Model -> Model
update act model =
case act of
MessageBoxAction msg ->
let
currentMessage' = MessageBox.update msg model.currentMessage
model' = {model | currentMessage = currentMessage'}
in
case MessageBox.sentMessage msg of
Nothing -> model'
Just str -> update (HandleSent str) model'
HandleSent str -> { model | posts = str::model.posts }