表单中的多个输入选择

时间:2012-02-08 11:19:55

标签: forms haskell yesod

我有一个表单,用户可以从预先存在的值列表中选择,或者创建一个新的(Text)值。

最优雅的编码方式是什么?

我最好(和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 :(得分:0)

您可以分解公共代码,使用模式匹配和保护,并使用接受访问器函数的高阶函数进行推广:

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