处理 Yesod 表单中的数据集合
Handling a collection of data in a Yesod Form
是否可以在 Yesod 中处理包含数据集合的表单?
我有一个表单,用户可以向其中添加多个人,在前端它目前看起来像这样:
{ people.map((person, key) => (
<td>
<input type="hidden" name={ `person[${key}][firstName]` } value={person.firstName} />
<input type="hidden" name={ `person[${key}][lastName]` } value={person.lastName} />
{ person.firstName } { person.lastName }
</td>
)) }
然后我希望能够像这样将其翻译到后端:
[Person "Michael" "Snoyman", Person "Ed" "Kmett"]
此列表的长度是可变的,因此它可以包含用户喜欢的 people
值中的任意数量的人。到目前为止,我一直无法弄清楚如何在 Yesod 中使用 FormInput
复制这种东西。
您可以通过定义 unFormInput
函数来创建自己的 FormInput
。这个函数可以从表单中拉取字段名,提取键,然后你可以使用ireq
来提升相关字段。
这可能看起来像
getPeople :: FormInput (your handler type) [People]
getPeople = FormInput $ \m l env fenv ->
(unFormInput (peopleField peopleKeys)) m l env fenv
where
peopleKeys = getPeopleKeys env
getPeopleKeys
此辅助函数将为表单中的人员生成所有键值。它们不需要是有效的,因为字段解析稍后会处理。
getPeopleKeys :: Env -> [Text]
getPeopleKeys env = mapMaybe extractKey (keys env)
where
extractKey :: Text -> Maybe Text
extractKey key = ... -- you could use e.g. regex here
-- to pull the keys out of the field names
-- and return Nothing otherwise
人物领域
此助手生成 FormInput
。它
- 获取键列表,
- 从每个生成一个
FormInput
- 为名字和姓氏生成一个字段
- 将这些字段变成
FormInput
s
- 产生一个
FormInput
将它们组合成一个 Person
- 将
FormInput
的结果连接成 FormInput ... [Person]
peopleField :: Monad m => RenderMessage (HandlerSite m) FormMessage => [Text] -> FormInput m [Person]
peopleField = mapM personField
where
personField :: Text -> Field ... Person
personField key = (liftA2 (Person)) (personFNameField) (personLNameField)
where
personFNameField = (ireq hiddenField) . fNameField key
personLNameField = (ireq hiddenField) . lNameField key
fNameField key = ... -- this outputs "person[${key}][firstName]"
lNameField key = ... -- etc.
是否可以在 Yesod 中处理包含数据集合的表单?
我有一个表单,用户可以向其中添加多个人,在前端它目前看起来像这样:
{ people.map((person, key) => (
<td>
<input type="hidden" name={ `person[${key}][firstName]` } value={person.firstName} />
<input type="hidden" name={ `person[${key}][lastName]` } value={person.lastName} />
{ person.firstName } { person.lastName }
</td>
)) }
然后我希望能够像这样将其翻译到后端:
[Person "Michael" "Snoyman", Person "Ed" "Kmett"]
此列表的长度是可变的,因此它可以包含用户喜欢的 people
值中的任意数量的人。到目前为止,我一直无法弄清楚如何在 Yesod 中使用 FormInput
复制这种东西。
您可以通过定义 unFormInput
函数来创建自己的 FormInput
。这个函数可以从表单中拉取字段名,提取键,然后你可以使用ireq
来提升相关字段。
这可能看起来像
getPeople :: FormInput (your handler type) [People]
getPeople = FormInput $ \m l env fenv ->
(unFormInput (peopleField peopleKeys)) m l env fenv
where
peopleKeys = getPeopleKeys env
getPeopleKeys
此辅助函数将为表单中的人员生成所有键值。它们不需要是有效的,因为字段解析稍后会处理。
getPeopleKeys :: Env -> [Text]
getPeopleKeys env = mapMaybe extractKey (keys env)
where
extractKey :: Text -> Maybe Text
extractKey key = ... -- you could use e.g. regex here
-- to pull the keys out of the field names
-- and return Nothing otherwise
人物领域
此助手生成 FormInput
。它
- 获取键列表,
- 从每个生成一个
FormInput
- 为名字和姓氏生成一个字段
- 将这些字段变成
FormInput
s - 产生一个
FormInput
将它们组合成一个Person
- 将
FormInput
的结果连接成FormInput ... [Person]
peopleField :: Monad m => RenderMessage (HandlerSite m) FormMessage => [Text] -> FormInput m [Person]
peopleField = mapM personField
where
personField :: Text -> Field ... Person
personField key = (liftA2 (Person)) (personFNameField) (personLNameField)
where
personFNameField = (ireq hiddenField) . fNameField key
personLNameField = (ireq hiddenField) . lNameField key
fNameField key = ... -- this outputs "person[${key}][firstName]"
lNameField key = ... -- etc.