Taxellool Taxellool - 3 months ago 17
AngularJS Question

Angularjs changing class name on url change

I'm trying to add 'active' class to my menu items on url change.

This is what I've tried so far : JSFiddle

(p.s: I tried to use stack's code snippets but it doesn't seem to work)

HTML:

<div ng-app="townApp">
<aside ng-controller="sideCtrl">
<ul id="sidebar">
<li ng-repeat="item in menuItems" ng-class="{'active': item.link == url}">
<a href="{{ item.link }}" ng-click="activate(item);">
<i class="glyphicon glyphicon-{{ item.icon }}"></i>
{{ item.text | uppercase }}
</a>
</li>
</ul>
</aside>
</div>


JS:

var townApp = angular.module('townApp', []);

townApp.controller('sideCtrl', function($scope, $location){
$scope.menuItems = [
{text:"dashboard", link:"#/dashboard", icon:"tint"},
{text:"payments", link:"#/payments", icon:"tint"},
{text:"graphs", link:"#/graphs", icon:"tint"},
];
$scope.url = '#' + $location.absUrl().split('/#')[1];
$scope.activate = function(item){
$scope.url = '#' + $location.absUrl().split('/#')[1];
}
});


This is working good on my local machine's page load.(not on jsfiddle which seems reasonable) but the problem is when clicking on each menu item, 'active' class will be added to previous clicked item.

Answer

See the updated Fiddle. The important change happened on these lines:

$scope.activate = function(item){
    $scope.url = item.link;
}

Basically, the activate function is triggered before the URL is changed, that is why it was taking the URL of the previous item.

An alternate solution would be to use $timeout (Fiddle):

$scope.activate = function(item){
  $timeout(function() {
    $scope.url = '#' + $location.absUrl().split('/#')[1];
  });
}

(Do not forget to inject $timeout into your controller in such case.)