我正在尝试在子网站表单中使用selectFieldList
但是我收到以下错误:
Couldn't match type 'IO' with 'HanderT master IO'
我在使用以下代码段时遇到此问题,其中子网站名为TestSub
(此子网站与主网站分开):
类型:
type TestHandler a = forall master. Yesod master
=> HandlerT TestSub (HandlerT master IO) a
type Form a = forall master. Yesod master
=> Html -> MForm (HandlerT TestSub (HandlerT master IO)) (FormResult a, WidgetT TestSub IO ())
Form&处理程序:
testForm :: Form (Text, Int)
testForm = renderBootstrap3 BootstrapBasicForm $ (,)
<$> areq textField (bfs MsgText) Nothing
<*> areq (selectFieldList [(MsgFirst, 1), (MsgSecond, 2)]) (bfs MsgSelect) Nothing
getTestHome :: TestHandler Html
getTestHome = do
(formWidget, _) <- generateFormPost testForm
defaultLayoutSub $ do
setTitleI MsgTest
[whamlet|^{formWidget}|]
当select字段替换为例如intField
时,表单和处理程序按预期工作。在Hoogle上查找selectFieldList
时,我发现选项字段(选择,广播,复选框)具有不同的签名(显示在下方),然后是“普通”字段。我怀疑这个区别是问题,但是没有找到解决办法而不必全部实现选项字段。
选项字段签名:
selectFieldList :: (Eq a, RenderMessage site FormMessage, RenderMessage site msg)
=> [(msg, a)]
-> Field (HandlerT site IO) a
正常字段签名:
intField :: (Monad m, Integral i, RenderMessage (HandlerSite m) FormMessage)
=> Field m i
有没有办法让选项字段在子网站上下文中工作,而不重新实现它们?
答案 0 :(得分:1)
通常最好通过调用lift
在主站点而不是子站点中运行表单。您还需要稍微修改您的类型同义词以匹配,但基本想法是替换:
(formWidget, _) <- generateFormPost testForm
与
(formWidget, _) <- lift $ generateFormPost testForm
修改强>
我仍然推荐上述方法。但是,要获得您要求的替代品,请将您的类型同义词更改为:
type Form a =
Html -> MForm (HandlerT HelloSub IO) (FormResult a, WidgetT HelloSub IO ())
然后使用liftHandlerT
:
liftHandlerT $ generateFormPost testForm
请注意,这不是设计使用子网站的方式,所以当你继续前进时,你可能会遇到更多的摩擦。
关于主翻译:你绝对可以利用它们,你只需要按照RenderMessage master MessageDataType
的约束。这就是整个地方FormMessage
使用的内容。
<强> EDIT2 强>
您可能会发现另一个有用的咒语:
defaultLayoutSub $ liftWidgetT widget