有人可以举例说明使用Snap突出显示网站菜单上的“有效”链接吗?或者至少告诉我你会怎么做 - 因为我不知道。
在其他Web框架中,我通常会将一个名为active
的上下文变量设置为活动页面应该是什么,然后我的html只会检查它:
<ul>
{% ifequal active "home" %}
<li class="active">
{% else %}
<li>
{% endifqual %}
<a href="/">Home</a>
</li>
{% ifequal active "about" %}
<li class="active">
{% else %}
<li>
{% endifequal %}
<a href="/about">About Us</a>
</li>
</ul>
heist中存在拼接,但我不确定如何使用它们来确定当前url是什么或设置上下文变量。
感谢@mightybyte和@Adam Bergmark,我已经解决了以下问题:
Haskell代码:
menuenuEntrySplice :: MonadSnap m => HeistT m Template
menuEntrySplice = do
requestPath <- lift $ withRequest (return . rqURI)
node <- getParamNode
let setActive n = if getAttribute "href" node == Just (decodeUtf8 requestPath)
then setAttribute "class" "active" n
else n
let aNode = Element "a" [("href", fromMaybe "/" $ getAttribute "href" node)] $ [TextNode (nodeText node)]
let liNode = setActive $ Element "li" [] [aNode]
return [liNode]
app :: SnapletInit App App
app = makeSnaplet "app" "An snaplet example application." Nothing $ do
....
addSplices [ ("menuEntry", liftHeist menuEntrySplice) ]
return $ App h s a
现在它已经在HTML中使用了:
<ul class="nav">
<menuEntry href="/">Home</menuEntry>
<menuEntry href="/contact">Contact</menuEntry>
</ul>
产生:
<ul class="nav">
<li class="active"> <a href="/">Home</a> </li>
<li> <a href="/contact">Contact</a> </li>
</ul>
答案 0 :(得分:4)
在snapframework.com网站上,我们使用javascript进行操作。在site.js结束时,您会发现此代码会将相应的类添加到相应的链接中。
if ($.url.segment(0)) {
$('.nav li.'+$.url.segment(0)).addClass('active');
} else {
$('.nav .home').addClass('active');
}
如果您想使用Heist执行此操作,则需要使用与上述模板使用的范例略有不同的范例。 Heist的全部要点(由Haskell的强静态类型系统辅助)是在视图和业务逻辑之间提供最强大的分离,因此您不能直接在模板中使用Haskell结构,如循环或条件。答案是创建新标签(使用拼接实现),完全符合您的要求。在您的模板中,您将使用它:
<ul>
<menuLink href="/">Home</menuLink>
<menuLink href="/about">About Us</menuLink>
</ul>
首先,请注意这是多么清洁。在您的方法中,您必须为每个链接重复相同的代码。在这里,我们可以保留模板DRY并且读取得非常好。
要实现menuLink标记,您需要一个看起来像这样的拼接拼接:
import Control.Monad.Trans.Class (lift) -- transformers
import Data.Text.Encoding (decodeUtf8)
import Text.XmlHtml (getAttribute, setAttribute, elementTag)
menuLinkSplice :: MonadSnap m => HeistT m Template
menuLinkSplice = do
requestPath <- lift $ withRequest (return . rqURI)
node <- getParamNode
let addActive n = if getAttribute "href" n == Just (decodeUtf8 requestPath)
then setAttribute "class" "active" n
else n
return [addActive (node { elementTag = "a" })]
然后,要将它们放在一起,您需要将该接头绑定到menuLink标记。在Snap应用程序中,您将使用:
addSplices [ ("menuLink", liftHeist menuLinkSplice) ]
您也可能会发现我的博文Looping and Control Flow in Heist有用(以及我的其他一些带有“抢劫”标签的帖子)。
答案 1 :(得分:0)
据我所知,Heist要求你把这种逻辑放入Haskell而不是Heist。例如,请参阅docs for Text.Templating.Heist:
中的此示例link :: Text -> Text -> X.Node
link target text = X.Element "a" [("href", target)] [X.TextNode text]
loginLink :: X.Node
loginLink = link "/login" "Login"
logoutLink :: Text -> X.Node
logoutLink user = link "/logout" (T.append "Logout " user)
loginLogoutSplice :: Splice MyAppMonad
loginLogoutSplice = do
user <- lift getUser
return [maybe loginLink logoutLink user]
这里不是将Bool传递给模板,而是让模板执行if / then逻辑,所有逻辑都在Haskell级别执行。这是我能给出的最佳答案。我对海斯特不熟悉;我知道你可以提出拼接论点,但我不清楚如何完成你的特定任务。