Vartan Arabyan
Vartan Arabyan

Reputation: 3073

node.js + jade + express: How can I create a navigation that will set class active if the path matches

I have come up with the following code but the problem is, there will be duplication of the anchor tag for each menu item.Is there a better way to do this?

                ul.nav
                    - if(menu="Home") 
                        li.active
                            a(href="#") Dashboard
                    else
                        li
                            a(href="#") Dashboard
                    li 
                        a(href="#") About
                    li 
                        a(href="#") Contact

Upvotes: 12

Views: 21034

Answers (7)

Liron
Liron

Reputation: 2032

Similar to @netAction's post, but dependent on the URL and not on the title.

each menuitem in [{title:'Home',url:'/'},{title:'About',url:'/about'},{title:'Contact',url:'/contact'}]
    if (path == menuitem.url)
        li.active
            a.active(href=menuitem.url) #{menuitem.title}
    else
        li
            a(href=menuitem.url) #{menuitem.title}

Combined with

app.use(function(req, res, next) {
    res.locals = {
        isAuthenticated: req.isAuthenticated(),
        path :req.path
    }

    next(); // make sure we go to the next routes and don't stop here
});

Upvotes: 0

Fizer Khan
Fizer Khan

Reputation: 92775

You can pass the pageName in the data.

each menu in ["Home", "Dashboard", "Contact", "About"]
    if (menu == pageName)
      li.active
        a(href="/#{menu}")= menu
    else
      li
        a(href="/#{menu}")= menu

You can call render

res.render("index", { pageName: 'Home'})

res.render("index", { pageName: 'Dashboard'})

res.render("index", { pageName: 'Contact'})

Upvotes: 2

netAction
netAction

Reputation: 1877

Very flexible without duplication:

ul
  each menuitem in [{title:'Home',url:'/'},{title:'About',url:'/about'},{title:'Contact',url:'/contact'}]
    if (menuitem.title == title)
      li.active
        a.active(href=menuitem.url) #{menuitem.title}
    else
      li
        a(href=menuitem.url) #{menuitem.title}

You need to set the page's current title.

Upvotes: 1

scottcheng
scottcheng

Reputation: 136

Here's an alternative that provides more flexibility in terms of anchor text and href than Peter's solution.

nav
  // suppose title local denotes the active nav item
  - var nav = {}; nav[title] = 'active'
  ul
    // pass title to li class via nav object
    li(class='#{nav.Home}')
      // different href and anchor text
      a(href='/') Home
    li(class='#{nav.About}')
      a(href='/about') About
    li(class='#{nav.Contact}')
      a(href='/contact') Contact

The caveat is that those li that are not active will have an undefined class, which does no harm in most cases.

Upvotes: 6

crussell
crussell

Reputation: 331

Found this in another question that was similar:

Use a ternary at each "li"

ul
    li(class=(title === 'Home' ? 'active' : ''))
        a(href='#') Home
    li(class=(title === 'Dashboard' ? 'active' : ''))
        a(href='#') Dashboard

You can setup your routes to pass the "menu" value instead of using "title" if you want:

exports.index = function(req, res) {
    res.render('index', {title: 'Home', menu: 'Home'});
}

Upvotes: 23

Arnaud Rinquin
Arnaud Rinquin

Reputation: 4306

I think it's better to set a body class to current path like so

body(class = currentPath)

So you can then use selectors such as

body.home .nav li.home, body.dashboard .nav li.dashboard {
  Style when current path
}

These selectors can be reduced to the minimal 'body.path .path' but it may be not isolated enough.

This will also be useful in the client side logic as this selectors could be used to determine the path in your JavaScript with something like

$("body.home").doSomethingSpecificToHome

This way your template has lot less logic.

Now, I don't think there is a way to set "currentPath" automatically depending on the URL. An helpers based on a 'url':'path' may be useful.

Upvotes: 1

Peter Lyons
Peter Lyons

Reputation: 146084

This has a little less duplication.

ul.nav
  each name in ["Dashboard", "About", "Contact"]
    if (menu=="Home")
      li.active
        a(href="#")= name
    else
      li
        a(href="#")= name

Adding the active class might be better just done in javascript or perhaps you can get the presentation you need with the straight CSS a:active selector.

Upvotes: 7

Related Questions