Yesod - 直接在模板中包含小部件
Yesod - include widget directly in template
我有一个脚手架 Yesod 应用程序并创建了一个简单的小部件,它看起来像这样,位于单独的模块中:
module Widget.Header where
import Prelude
import Yesod
twitterWidget :: MonadWidget m => String -> m ()
twitterWidget twitteruser = do
toWidgetBody([hamlet| <a href="https://twitter.com/#{twitteruser}" .twitter-follow-button data-show-count="false">Follow @#{twitteruser}
<script async src="//platform.twitter.com/widgets.js" charset="utf-8">
|])
我已将此模块包含到 .cabal 文件中,我可以将其加载到处理程序中,一切正常。
twitterUsername :: String
twitterUsername = "someusername"
getHomeR :: Handler Html
getHomeR = do
(formWidget, formEnctype) <- generateFormPost sampleForm
let submission = Nothing :: Maybe FileForm
handlerName = "getHomeR" :: Text
defaultLayout $ do
let (commentFormId, commentTextareaId, commentListId) = commentIds
aDomId <- newIdent
setTitle "Some title"
twitterWidget twitterUsername
$(widgetFile "homepage")
所以我想做的是直接在另一个模板中使用它,但是当我尝试这样做时:
^{twitterWidget twitterUsername}
我明白了
• Ambiguous type variable ‘m1’ arising from a use of ‘toWidget’
prevents the constraint ‘(ToWidget App (m1 ()))’ from being solved.
Probable fix: use a type annotation to specify what ‘m1’ should be.
These potential instances exist:
instance (site' ~ site, IO ~ m, a ~ ()) =>
ToWidget site' (WidgetT site m a)
-- Defined in ‘Yesod.Core.Widget’
...plus one instance involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In the second argument of ‘(GHC.Base..)’, namely ‘toWidget’
In the expression: asWidgetT GHC.Base.. toWidget
In a stmt of a 'do' block:
(asWidgetT GHC.Base.. toWidget) (twitterWidget twitterUsername)
所以我的问题是,在网站各处的模板中加载多个小部件服务于不同目的的正确方法是什么?
改变你的
module Widget.Header where
import Prelude
import Yesod
twitterWidget :: MonadWidget m => String -> m ()
twitterWidget twitteruser = do
toWidgetBody([hamlet| <a href="https://twitter.com/#{twitteruser}" .twitter-follow-button data-show-count="false">Follow @#{twitteruser}
<script async src="//platform.twitter.com/widgets.js" charset="utf-8">
|])
更像是
module Widget.Header where
import Import
twitterWidget :: Yesod site => String -> WidgetT site IO ()
twitterWidget twitteruser = do
toWidgetBody([hamlet| <a href="https://twitter.com/#{twitteruser}" .twitter-follow-button data-show-count="false">Follow @#{twitteruser}
<script async src="//platform.twitter.com/widgets.js" charset="utf-8">
|])
这样 m
肯定会变成 IO
而 Haskell 就不用想出来了。
我有一个脚手架 Yesod 应用程序并创建了一个简单的小部件,它看起来像这样,位于单独的模块中:
module Widget.Header where
import Prelude
import Yesod
twitterWidget :: MonadWidget m => String -> m ()
twitterWidget twitteruser = do
toWidgetBody([hamlet| <a href="https://twitter.com/#{twitteruser}" .twitter-follow-button data-show-count="false">Follow @#{twitteruser}
<script async src="//platform.twitter.com/widgets.js" charset="utf-8">
|])
我已将此模块包含到 .cabal 文件中,我可以将其加载到处理程序中,一切正常。
twitterUsername :: String
twitterUsername = "someusername"
getHomeR :: Handler Html
getHomeR = do
(formWidget, formEnctype) <- generateFormPost sampleForm
let submission = Nothing :: Maybe FileForm
handlerName = "getHomeR" :: Text
defaultLayout $ do
let (commentFormId, commentTextareaId, commentListId) = commentIds
aDomId <- newIdent
setTitle "Some title"
twitterWidget twitterUsername
$(widgetFile "homepage")
所以我想做的是直接在另一个模板中使用它,但是当我尝试这样做时:
^{twitterWidget twitterUsername}
我明白了
• Ambiguous type variable ‘m1’ arising from a use of ‘toWidget’
prevents the constraint ‘(ToWidget App (m1 ()))’ from being solved.
Probable fix: use a type annotation to specify what ‘m1’ should be.
These potential instances exist:
instance (site' ~ site, IO ~ m, a ~ ()) =>
ToWidget site' (WidgetT site m a)
-- Defined in ‘Yesod.Core.Widget’
...plus one instance involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In the second argument of ‘(GHC.Base..)’, namely ‘toWidget’
In the expression: asWidgetT GHC.Base.. toWidget
In a stmt of a 'do' block:
(asWidgetT GHC.Base.. toWidget) (twitterWidget twitterUsername)
所以我的问题是,在网站各处的模板中加载多个小部件服务于不同目的的正确方法是什么?
改变你的
module Widget.Header where
import Prelude
import Yesod
twitterWidget :: MonadWidget m => String -> m ()
twitterWidget twitteruser = do
toWidgetBody([hamlet| <a href="https://twitter.com/#{twitteruser}" .twitter-follow-button data-show-count="false">Follow @#{twitteruser}
<script async src="//platform.twitter.com/widgets.js" charset="utf-8">
|])
更像是
module Widget.Header where
import Import
twitterWidget :: Yesod site => String -> WidgetT site IO ()
twitterWidget twitteruser = do
toWidgetBody([hamlet| <a href="https://twitter.com/#{twitteruser}" .twitter-follow-button data-show-count="false">Follow @#{twitteruser}
<script async src="//platform.twitter.com/widgets.js" charset="utf-8">
|])
这样 m
肯定会变成 IO
而 Haskell 就不用想出来了。