Обработка сбора данных в форме Yesod - PullRequest
0 голосов
/ 05 сентября 2018

Возможно ли в 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 может быть столько людей, сколько ему нравится. До сих пор я не мог понять, как воспроизвести подобные вещи, используя FormInput в Yesod.

1 Ответ

0 голосов
/ 09 сентября 2018

Вы можете создать свой собственный FormInput, определив функцию unFormInput. Эта функция может извлекать имена полей из формы, извлекать ключи, а затем вы можете использовать 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

peopleField

Этот помощник производит FormInput. Это

  1. принимает список ключей,
  2. генерирует FormInput от каждого
    1. генерирует поле для имени и фамилии
    2. превращает эти поля в FormInput с
    3. производит FormInput, который объединяет их в Person
  3. объединяет результаты FormInput s в 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.
...