Множество възможности за избор на въвеждане във формуляр

Имам формуляр, в който потребителят може или да избере от предварително съществуващ списък със стойности, или да създаде нова (текстова) стойност.

Кой ще бъде най-елегантният начин за кодиране на това?

Най-добрият ми (и 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

И накарайте манипулатора да реши дали да изпрати отново формуляра или да продължи според резултата.

Някакви по-добри/по-кратки предложения? Моят реален формуляр има две такива полета за избор/създаване, което прави структурата на данните и обработката още по-досадна. Благодаря,


person Uri Barenholz    schedule 08.02.2012    source източник


Отговори (1)


Можете да отделите общия код, да използвате съвпадение на шаблони и предпазители и да обобщите с функция от по-висок ред, която приема функциите за достъп:

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
person pat    schedule 08.02.2012
comment
Благодаря, това наистина прави кода по-чист. Надявах се, че ще има някакъв начин да се избегне необходимостта от проверка на резултата в манипулатора като цяло (което може да се направи за въвеждане на едно поле чрез проверка/проверка на Yesod). Ако не, тогава това вероятно е най-доброто решение. - person Uri Barenholz; 09.02.2012