4

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>

強盗にはスプライスがありますが、それらを使用して現在の 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>
4

2 に答える 2

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

また、私のブログ投稿「Heistのループと制御フロー」が役立つ場合があります(「heist」タグが付いた他のいくつかの投稿も同様です)。

于 2012-07-30T15:35:57.640 に答える
0

私の知る限り、Heist では、この種のロジックを Heist ではなく Haskell に入れる必要があります。たとえば、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 レベルで実行されます。それが私ができる最善の答えです。私は強盗に慣れていません。スプライス引数を与えることができることは知っていますが、特定のタスクをどのように達成するかは不明です。

于 2012-07-30T02:41:10.197 に答える