如何使用不同数量的输入字段动态生成表单?
我最接近的是:
listEditForm :: [String] -> Html -> MForm App App (FormResult Text, Widget)
listEditForm xs = renderDivs $ mconcat [ areq textField (String.fromString x) Nothing | x <- xs]
但是它的结果类型为Text
,而不是[Text]
,因为Text
是Monoid
的实例的巧合,例如它以Int
失败。
我有一个工作的替代尝试,它结合了几种形式,但不知何故它只适用于这个玩具示例,而真正的尝试失败了奇怪。无论如何,我认为这不是正确的方法:
data MapPair = MapPair { mpKey :: T.Text, mpValue :: Maybe T.Text }
editForm mmp = renderTable $ MapPair
<$> areq textField "Key" (mpKey <$> mmp)
<*> aopt textField "Value" (mpValue <$> mmp)
pair2mp (v,k) = MapPair { mpKey = v, mpValue = Just k }
getEditR = do
sess <- getSession
let sesslist = Map.toList $ Map.map (decodeUtf8With lenientDecode) sess
forms <- forM sesslist (\a -> generateFormPost $ editForm $ Just $ pair2mp a)
defaultLayout [whamlet|
<h1>Edit Value Pairs
$forall (widget,enctype) <- forms
<form method=post action=@{EditR} enctype=#{enctype}>
^{widget}
<input type=submit>
|]
postEditR = do
sess <- getSession
let sesslist = Map.toList $ Map.map (decodeUtf8With lenientDecode) sess
forM_ sesslist (\a -> do
((res,_),_) <- runFormPost $ editForm $ Just $ pair2mp a
case res of
(FormSuccess (MapPair {mpKey=mk, mpValue=(Just mv)})) -> setSession mk mv
_ -> return ()
)
defaultLayout [whamlet|ok|]
答案 0 :(得分:6)
Duh,使用monadic表单实际上很容易(参见下面的代码)。
我最头疼的是额外的文本字段,以确保接收答案的处理程序也可以推断出相应的问题。也许我可以隐藏那些文本字段,使它们不可编辑,或者找到另一种方法(但我对Html还不太了解)。
listEditMForm :: [(String,Int)] -> Html -> MForm App App (FormResult [(FormResult Int, FormResult Text)], Widget)
listEditMForm xs extra = do
ifields <- forM xs (\(s,i) -> mreq intField (String.fromString s) (Just i))
tfields <- forM xs (\(s,i) -> mreq textField (String.fromString s) (Just $ pack s))
let (iresults,iviews) = unzip ifields
let (tresults,tviews) = unzip tfields
let results = zip iresults tresults
let views = zip iviews tviews
let widget = [whamlet|
#{extra}
<h1>Multi Field Form
$forall (iv,tv) <- views
Field #
#{fvLabel iv}: #
^{fvInput tv} #
^{fvInput iv}
<div>
|]
return ((FormSuccess results), widget)
还有一些我不知道的丑陋的东西,比如总是将结果总是包装在最外层的FormSuccess
构造函数中,但我想这实际上取决于每个用例(例如单个FormFailure或FormMissing应该可能使整个表单失败/丢失,但在某些情况下可能不需要。)
所有的压缩和解压缩都可以更整齐地完成,但我想在我的情况下我只创建一个组合字段textintField
。我想我知道怎么做,但如果有一个组合字段的功能,它会很简洁。