在Elm中,我有一个具有嵌套属性的模型,如:
model =
{ name = ""
, disruptedFields =
{ advertising =
{ name = "Advertising"
, checked = False
}
, travel =
{ name = "Travel"
, checked = False
}
, utilities =
{ name = "Utilities"
, checked = False
}
}
}
disruptedFields
包含复选框的值列表。当我点击复选框时,我向UpdateDisruptedField
发送了一条更新消息,目前看起来像是:
UpdateDisruptedField value ->
let
fieldCollection = model.disruptedFields
field = fieldCollection.advertising
in
{ model | disruptedFields =
{ fieldCollection | advertising =
{ field | checked = (not value) }
}
}
我的更新功能已硬编码到model.disruptedField.advertising
和field
变量中的advertising
。这对我有用,但我不知道这个函数是通用的。
如何将记录传递到UpdateDisruptedField以便我可以将其设为通用?
答案 0 :(得分:6)
这是具有许多输入字段的Elm应用程序的常见问题。创建通用更新函数有两种方法可以减少代码重复。
使用输入标识符扩展更新消息,然后使用case checkboxType of
添加另一级别的开关,并使用所有嵌套记录处理更新。每次在模型中添加新字段时,都必须使用额外的分支扩展更新以处理更新。
使用词典重新构建模型,并以适当的通用方式处理更新。
我更喜欢第二个选项,因为更新嵌套的记录是一件苦差事。
请考虑以下示例:
module Main exposing (..)
import Html exposing (div, input, text, label)
import Html.App exposing (beginnerProgram)
import Html.Events exposing (onCheck)
import Html.Attributes exposing (type', checked)
import Dict
(=>) : a -> b -> ( a, b )
(=>) a b =
( a, b )
main =
beginnerProgram { model = model, view = view, update = update }
model =
{ name = ""
, disruptedFields =
Dict.fromList
[ "advertising"
=> { name = "Advertising"
, checked = False
}
, "travel"
=> { name = "Travel"
, checked = False
}
, "utilities"
=> { name = "Utilities"
, checked = False
}
]
}
type Msg
= Check String Bool
view model =
let
checkbox ( key, data ) =
label []
[ text data.name
, input
[ type' "checkbox"
, checked data.checked
, onCheck (Check key)
]
[]
]
in
div []
(model.disruptedFields
|> Dict.toList
|> List.map checkbox
)
update msg model =
case msg of
Check checkboxId checked ->
let
updateRecord =
Maybe.map (\checkboxData -> { checkboxData | checked = checked })
disruptedFieldsUpdated =
Dict.update checkboxId
updateRecord
model.disruptedFields
in
{ model | disruptedFields = disruptedFieldsUpdated }
请注意,我一直在使用=>
运算符让元组看起来更漂亮。
disruptedFields
现在是一个词典,使用String
键来识别每个复选框。
答案 1 :(得分:1)
为什么不使用Dict
而不是明确列出所有字段?