1

我正在尝试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 ())

表单和处理程序:

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}|]

when the select field is replaced with for instance an intFieldthe form and handler work as expected. 在寻找selectFieldListHoogle 时,我发现选项字段(选择、单选、复选框)与“正常”字段具有不同的签名(如下所示)。我怀疑这种差异是问题所在,但还没有找到解决方法,而不必完全实现选项字段。

选项字段签名:

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

有没有办法让选项字段在子站点上下文中工作,而无需重新实现它们?

4

1 回答 1

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

编辑2

还有一种你可能会觉得有用的咒语:

defaultLayoutSub $ liftWidgetT widget
于 2014-11-18T14:53:04.683 回答