如何为Elm中的嵌套记录制作通用更新功能 [英] How to make a generic update function for a nested record in Elm
问题描述
在榆树中,我有一个带有嵌套属性的模型,例如:
In Elm I have a model with nested attributes like:
model =
{ name = ""
, disruptedFields =
{ advertising =
{ name = "Advertising"
, checked = False
}
, travel =
{ name = "Travel"
, checked = False
}
, utilities =
{ name = "Utilities"
, checked = False
}
}
}
disruptedFields
包含复选框的值列表。当我单击复选框时,我向 UpdateDisruptedField
发送一条更新消息,该消息当前如下所示:
disruptedFields
contains a list of values for checkboxes. When I click on the checkbox I send an update message to UpdateDisruptedField
, which currently looks like:
UpdateDisruptedField value ->
let
fieldCollection = model.disruptedFields
field = fieldCollection.advertising
in
{ model | disruptedFields =
{ fieldCollection | advertising =
{ field | checked = (not value) }
}
}
我的更新函数是在字段
和广告$ c中硬编码为
model.disruptedField.advertising
$ c>变量。这对我有用,但是我仍然使该函数成为通用函数。
My update function is hard-coded to model.disruptedField.advertising
in the field
and advertising
variables. This is working for me, but I'm stuck making the function generic.
如何将记录传递给UpdateDisruptedField以便使它通用? / strong>
How do I pass the record into UpdateDisruptedField so I can make it generic?
推荐答案
对于输入框很多的Elm应用程序,这是一个常见问题。创建通用更新功能以减少代码重复的方法有两种。
This is a common problem for Elm apps with many input fields. There are two approaches for creating a generic update function to reduce code repetition.
-
使用输入的标识符扩展消息以进行更新然后使用
case checkboxType为
添加另一个级别的开关,并使用所有嵌套记录处理更新。每次您在模型中添加新字段时,都必须使用一个额外的分支来扩展更新以处理更新。
Extend the message for update with identifier for an input and then add another level of switch with
case checkboxType of
and handle the update with all the nested Records. Every time you will add a new field in the model, you will have to extend the update with an extra branch for handling the update.
重新组织您的结构使用Dictionary进行建模,并以适当的通用方式处理更新。
Re-structure your model with Dictionaries and handle the update in a proper generic way.
我更喜欢第二种选择,因为更新嵌套记录
I prefer the second option, because updating nested Records is a chore.
请考虑以下示例:
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 }
请注意,我一直在使用 => ;
运算符使元组看起来更好。
Please note, that I've been using =>
operator to make Tuples look nicer.
disruptedFields
现在是一个字典,即使用 String
键来标识每个复选框。
disruptedFields
is now a Dictionary, that uses String
keys to identify every checkbox.
这篇关于如何为Elm中的嵌套记录制作通用更新功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!