Himanshu Yadav
Himanshu Yadav

Reputation: 13585

Meteor: Change the class of link on click

Template:

<template name="header">
    <div class="blog-masthead">
        <div class="container">
            <nav class="blog-nav">
              <a class="blog-nav-item {{active}}" href="{{pathFor 'homePage'}}">Home</a>
              {{#if currentUser}}
                <a class="blog-nav-item {{active}}" href="#">{{Meteor.userId}}</a>
              {{else}}
                <a class="blog-nav-item {{active}}" href="{{pathFor 'loginPage'}}">Login</a>
                <a class="blog-nav-item {{active}}" href="{{pathFor 'signUpPage'}}">Sign Up</a>
              {{/if}}
              <a class="blog-nav-item {{active}}" href="#">About</a>
            </nav>
        </div>
    </div>
</template>

header.js

Template.header.events({
    'click a': function(e) {
        e.preventDefault();
        this.active?"active":"";
    }
});

I just want to make set click link's class as active. Clicked link class should look like class="blog-nav-item active".

Upvotes: 2

Views: 3722

Answers (3)

Matyas
Matyas

Reputation: 13702

The example below relies on iron-router and presents a reactive approach for adding the active class

First should modify the template to be:

<a class="blog-nav-item {{active 'homePage'}}" href="{{pathFor 'homePage'}}">Home</a>

And then the appropriate helper for it should be:

Template.name.helpers({
    active: function(routeName) {
        var curRoute = Router.current().route;
        return curRoute.name === routeName ? 'active' : '';
    }
});

Edit v1.0+

As of iron-router 1.0, A route's name is now accessible at
route.getName() (previously it was route.name).

In particular, you'll need to write return
curRoute.getName() === routeName ? 'active' : '';

Thank you @jrbedard for the notification

Upvotes: 8

Peppe L-G
Peppe L-G

Reputation: 8345

I guess this would be the "Meteor way" you wanted:

<template name="menu">
    <ul>
        <li class="{{#if isCurrentPage 'pageA'}}active{{/if}}">
            <a href="{{pathFor 'pageA'}}">Page A</a>
        </li>
        <li class="{{#if isCurrentPage 'pageB'}}active{{/if}}">
            <a href="{{pathFor 'pageB'}}">Page B</a>
        </li>
        <li class="{{#if isCurrentPage 'pageC'}}active{{/if}}">
            <a href="{{pathFor 'pageC'}}">Page C</a>
        </li>
    </ul>
</template>
Router.onBeforeAction(function(){
    Session.set('currentRouteName', Router.current().route.name)
})

Template.menu.helpers({
    isCurrentPage: function(pageName){
        return Session.equals('currentRouteName', pageName)
    }
})

Router.current().route.name do evaluate to the current page name in the latest version of iron router, but I don't know if that's part of the public API one should use.

EDIT

Router.current() is apparently reactive, so all JavaScript code you need is the following:

Template.menu.helpers({
    isCurrentPage: function(pageName){
        return Router.current().route.name == pageName
    }
})

Upvotes: 6

Peppe L-G
Peppe L-G

Reputation: 8345

You can solve it with JavaScript only:

Template.header.events({
    'click .blog-nav-item': function(event, template){

        // Remove the class 'active' from potentially current active link.
        var activeLink = template.find('.blog-nav-item')
        if(activeLink){
            activeLink.classList.remove('active')
        }

        // Add the class 'active' to the clicked link.
        event.currentTarget.classList.add('active')

    } 
})

Upvotes: 1

Related Questions