31

I have a navigation bar in my parent jade template and I'd like to highlight the item which is currently in view. So if I'm on the blog page,

ul
  li Home
  li.active Blog
  li Contact Us
  li About

Without copying the navigation bar structure into each child template, is there a way to have the parent template see what page it's extending and apply the active class accordingly?

Adam Grant
  • 12,477
  • 10
  • 58
  • 65

4 Answers4

70

parent.jade

doctype 5

html
  block link
    -var selected = 'home'; //default

  -var menu = { 'home': '/home', 'blog': '/blog', 'contact': '/contact' };

  body
    nav
      ul
        each val, key in menu
          li
            if selected === key
              a.selected(href=val, title=key)= key
            else
              a(href=val, title=key)= key

child.jade

extends parent

block link
  -var selected = 'blog';
Pickels
  • 33,902
  • 26
  • 118
  • 178
  • 1
    Really? There's no simpler way to do this? -sad face- – Costa Michailidis Dec 16 '14 at 21:39
  • I am using PyJade, to get this to work i had to do "each val, key in menu.iteritems()" +1 for sure. Thanks – SolThoth Apr 15 '15 at 04:01
  • @Costa solution is simpler and more performant since is done with css no iteration, no if statement, no duplication of a tag – dciccale Aug 27 '15 at 21:41
  • This solution is not easy to maintain because if you change your routes names, you have *also* to edit their definition in the template. @Costa solution in this way brings a more robust one. – smonff Nov 27 '17 at 11:09
8

Here's a simpler way:

Use this in your layout.jade (where nav is the name of the page that's active. nav = 'about' for example)

ul(class="#{nav}")
  li.home Home
  li.blog Blog
  li.contact Contact Us
  li.about About

Then put this is your CSS:

ul.home li.home,
ul.blog li.blog,
ul.contact li.contact,
ul.about li.about {
    color: red;
}

The only css rule that will apply is the one whose ul class exists. You'll need to pass in a variable nav that equals 'about', 'home', 'contact', or 'blog' depending on what page you're on.

smonff
  • 3,399
  • 3
  • 36
  • 46
Costa Michailidis
  • 7,691
  • 15
  • 72
  • 124
  • If you're using Sass, you may also be able to do this: http://codepen.io/ajkochanowicz/pen/zGvgxz – Adam Grant May 07 '15 at 18:20
  • Hey i did the same but in the inspector it says "undefined". I have my nav in a separate .jade-file (I'm new in jade ) What am i doing wrong? – moeses Jun 28 '16 at 13:45
  • @moesphemie - a bit late now, but make sure you're putting your "var nav= 'home'" definition inside the correct block in jade. – itchyspacesuit May 18 '18 at 16:46
5

Use the Current object with a ternary expression. All is in the documentation.

You can use the object properties to generate your active menu like so. If you want to use folders in your navigation menu (Jade version) :

ul(class="nav-menu")
            li: a(class="#{ current.path[0] === 'index' ? 'active' : '' }", href="/") home
            li: a(class="#{ current.path[0] === 'about' ? 'active' : '' }", href="/about/") about
lraboteau
  • 71
  • 2
  • 5
  • Doesn't seem to work with current Jade: ` 24| #navbar.collapse.navbar-collapse 25| ul.nav.navbar-nav > 26| li(class="#{ current.path[0] == 'index' ? 'active' : '' }") 27| a(href='/') Main 28| li(class="#{ current.path[0] == 'sub' ? 'active' : '' }") 29| a(href='#sub') Subscribe Cannot read property 'path' of undefined ` – JD Allen Jul 22 '20 at 15:49
0

Well, above solution is very clear but if someone is looking more controls over menus then there is a module available for node.js. Use this and you would have complete control over menus.

Use Case : When menus visibles based on roles

https://www.npmjs.com/package/active-menu

Irfan Raza
  • 2,859
  • 1
  • 22
  • 29