如何在Yesod中使用blaze代码编写小部件?

时间:2016-08-10 14:17:39

标签: haskell yesod

我正在尝试编写一个没有任何哈姆雷特部分的yes应用程序。我的问题是关于表单:我可以使用Applicative生成表单,但我不能直接在我的blaze代码中使用它。

这是一个哈姆雷特版本的例子:

-- actual form example
userForm :: Form User
userForm = renderDivs $ User
  <$> areq textField "Login" Nothing
-- usage example
getPageR :: Handler Html
getPageR = do
  ((_, widget), enctype') <- runFormGet userForm
  defaultLayout [whamlet|
                 <form method=post action=@{PageR} enctype=#{enctype'}>
                 ^{widget} -- This widget include.
                 <button>Submit|]

但是如何在没有哈姆雷特的情况下重写呢?我目前的代码是这样的:

getPageR = do
  ((_, widget), enctype') <- runFormGet userForm
  defaultLayout $ do
    toWidgetBody $ \render -> do
      H.div ! A.id "form" $ do
        H.form ! A.method "post" ! A.action (action' render) ! A.enctype (enct' enctype) $ ""
        -- widget include?
        H.button "Submit!"
   where
     action' = \render -> toValue $! render (PageR) []
     enct'   = toValue . renderHtml . toHtml

显然,火焰代码的类型是Html,但userForm类型是Widget,因此无法连接。我只能在toWidgetBody函数之后添加小部件,但是表单将在所有内容之后。有没有办法在blaze组合器中​​包含表单(通过将其呈现为Html,可能?)而不使用hamlet ^{widget}构造?

1 个答案:

答案 0 :(得分:2)

使用widgetToPageContent功能。

然后,您可以通过调用pageBody并应用Html功能来了解render

getPageR :: Handler Html -- same as: HandlerT App IO Html
getPageR = do
  ((_, widget), enctype') <- runFormGet sampleForm
  content <- widgetToPageContent widget
  defaultLayout $ do
    toWidgetBody $ \render -> do
      H.div ! A.id "form" $ do
        H.form ! A.method "post" ! A.action (action' render)
                                 ! A.enctype (enct' enctype') $ ""
        pageBody content render
        H.button "Submit!"
   where
     action' = \render -> toValue $! render (PageR) []
     enct'   = toValue . renderHtml . toHtml
     (!) = (H.!)
     toValue = H.toValue