Множественный выбор ввода в форме - PullRequest
0 голосов
/ 08 февраля 2012

У меня есть форма, в которой пользователь может либо выбрать из существующего списка значений, либо создать новое (текстовое) значение.

Каким будет самый элегантный способ кодирования этого?

Мой лучший (и IMO не очень элегантный) способ сделать это - определить:

data MyInput = MyInput {createNew :: Bool, newVal :: Maybe Text, existingVal :: Maybe Text}

myForm :: [(Text,Text)] -> Html -> MForm MySite MySite (FormResult MyInput,Widget)
myForm exisingVals = renderTable $ MyInput
    <$> areq boolField "Create new" (Just False)
    <*> aopt textField "New val" Nothing
    <*> aopt (selectField existingVals) "Existing values" Nothing

И как только форма будет получена, передайте результат через что-то вроде:

getMyValue :: MyInput -> Either ErrorMsg Text
getMyValue i = if createNew i
                   then if newVal i == Nothing || existingVal i /= Nothing
                            then Left "Missing new value or illegal input"
                            else Right . fromJust . newVal $ i
                   else if existingVal i == Nothing || newVal i /= Nothing
                            then Left "Missing selection or illegal input"
                            else Right . fromJust . existingVal $ i

И обработчик должен решить, следует ли повторно отправить форму или действовать в соответствии с результатом.

Какие-нибудь более качественные / короткие предложения?Моя настоящая форма имеет два таких поля выбора / создания, что делает структуру данных и обработку еще более утомительным.Спасибо,

1 Ответ

0 голосов
/ 08 февраля 2012

Вы можете выделить общий код, использовать сопоставление с образцом и охрану, а также обобщить с помощью функции высшего порядка, которая принимает функции доступа:

import Control.Arrow ((&&&))

getVal isNew newVal oldVal i | isNew i   = checkVal "new value" $ (newVal &&& oldVal) i
                             | otherwise = checkVal "selection" $ (oldVal &&& newVal) i
  where checkVal _ (Just val, Nothing) = Right val
        checkVal name _                = Left $ "Missing " ++ name ++ " or illegal input"

getMyVal = getVal createNew newVal existingVal
...