Toggle active class on item with angular.js

4.2k Views Asked by At

How can I toggle active class on element if I have the following code?

<div class="searchandfilter">
    <span ng-repeat="taxonomy in taxonomies" class="tab-controller" ng-class="{'active': $index == 0}">
        <ul>
            <li class="tab" ng-click="onClickTab(taxonomy)">{{taxonomy.name}}</li>
        </ul>
        <span class="tab-content">
            <span ng-repeat="child in taxonomy.children">
                <input type="checkbox" checked="child.value" />{{child.name}}
            </span>
        </span>
    </span>

On load I need to set the first tab-conroller span to active, which is now correct but I can't toggle the active class onclick. The number of tabs is dynamic, so it can be 1 or 10. Currently it generates the tabs like this:

<span class="tab-controller ng-scope active" ng-class="{'active': $index == 0}" ng-repeat="taxonomy in taxonomies">
<ul>
<li class="tab ng-binding" ng-click="onClickTab(taxonomy)">Tab 1</li>
</ul>
</span>

<span class="tab-controller ng-scope" ng-class="{'active': $index == 0}" ng-repeat="taxonomy in taxonomies">
<ul>
<li class="tab ng-binding" ng-click="onClickTab(taxonomy)">Tab2</li>
</ul>
</span>
3

There are 3 best solutions below

0
On BEST ANSWER

You can do this by passing the index and setting a scope variable.

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

app.controller('myController', function($scope) {
  $scope.taxonomies = [
    {name: 'a', children: [{name: 'a', value: false}]}, 
    {name: 'b', children: [{name: 'a', value: true}, 
                           {name: 'b', value: false}]}
  ];
  
  $scope.onClickTab = function(idx) {
    $scope.selectedIndex = idx;
  };
  
  $scope.selectedIndex = 0;
});
.active {
  color: green;
  font-weight: bold;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<div ng-app='app' ng-controller='myController'>

  <div class="searchandfilter">
    <span ng-repeat="taxonomy in taxonomies" class="tab-controller" ng-class="{'active': $index == selectedIndex}">
        <ul>
            <li class="tab" ng-click="onClickTab($index)">{{taxonomy.name}}</li>
        </ul>
        <span class="tab-content">
            <span ng-repeat="child in taxonomy.children">
                <input type="checkbox" ng-model="child.value">{{child.name}}
            </span>
    </span>
    </span>
  </div>
</div>

The problem with that approach is if the taxonomies change, the selectedIndex may no longer match up with selected tab so instead of tracking index, you can just track the entire object:

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

app.controller('myController', function($scope) {
  $scope.taxonomies = [
    {name: 'a', children: [{name: 'a', value: false}]}, 
    {name: 'b', children: [{name: 'a', value: true}, 
                           {name: 'b', value: false}]}
  ];
  
  $scope.onClickTab = function(selected) {
    $scope.selected = selected;
  };
  
  $scope.selected = $scope.taxonomies[0];
});
.active {
  color: green;
  font-weight: bold;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<div ng-app='app' ng-controller='myController'>

  <div class="searchandfilter">
    <span ng-repeat="taxonomy in taxonomies" class="tab-controller" ng-class="{'active': taxonomy === selected}">
        <ul>
            <li class="tab" ng-click="onClickTab(taxonomy)">{{taxonomy.name}}</li>
        </ul>
        <span class="tab-content">
            <span ng-repeat="child in taxonomy.children">
                <input type="checkbox" ng-model="child.value">{{child.name}}
            </span>
    </span>
    </span>
  </div>
</div>

0
On

You need to have some property in your tabs to be able to compare against the $index in the ng-repeat.

For example:

<div class="tab-controller" ng-class="{'active': $index == currentTab}" ng-repeat="taxonomy in taxonomies">
    <ul>
        <li class="tab" ng-click="onClickTab(taxonomy.tab)">{{ taxonomy.name }}</li>
    </ul>
</div>

And taxonomies should be an array of objects, something like:

var taxonomies = [
    { id: 0, name: 'Tab 1', tab: 'whatever you need here'},
    { id: 1, name: 'Tab 2', tab: 'whatever you need here'},
    { id: 2, name: 'Tab 3', tab: 'whatever you need here'}
];

And when you call your function onClickTab it should set the variable scope.currentTab to the id of the clicked tab.

Hope it helps.

0
On

sorry if am wrong,try this

http://plnkr.co/edit/FdueM4rAvd4k6hClK1HR?p=preview

your html will be

<html>

<head>
  <script data-require="angular.js@*" data-semver="1.4.0-beta.6" src="https://code.angularjs.org/1.4.0-beta.6/angular.js"></script>
  <link rel="stylesheet" href="style.css" />
  <script src="script.js"></script>
</head>

<body ng-app="app">

  <div class="searchandfilter" ng-controller="tab-controller">

    <span ng-repeat="taxonomy in taxonomies">
        <ul  ng-class="{'active': $index == selectedIndex}">
            <li class="tab" ng-click="onClickTab(taxonomy.id)">{{taxonomy.name}}
              <br/>
                <span class="tab-content">
                  <span ng-repeat="child in taxonomy.children">
                      <input type="checkbox" ng-model="child.value" />{{child.name}} 
                  </span>
                </span>
            </li>
        </ul>
    </span>
  </div>

</body>
</html>

angular js code will be

  var app = angular.module("app",[]);
    app.controller('tab-controller',['$scope',function($scope){

    $scope.taxonomies = [
    { id: 0, name: 'hello' , children:[{name:"test1",value:true},{name:"test2",value:false}]},
    { id: 1, name: 'how' , children:[{name:"test5", value: false}]},
    { id: 2, name: 'are you',children:[{name:"test4",value: true}]}
    ];

    $scope.onClickTab= function(x){
      $scope.selectedIndex= x;
    };

  }]);

css code will be

.active{
  background-color:green;
}

body {
    background-color: yellow;
}