40

I want to add an active class on click in a list, i tried the following code, but it adds the active class on all my items :/ :

HTML :

<div class="filters_ct" ng-controller="selectFilter">
    <ul>
        <li ng-repeat="filters in filter"  ng-click="select(item)" ng-class="{sel: item == selected}">
            <span class="filters_ct_status"></span>
            {{filters.time}}
        </li>
    </ul>
</div>

Js :

  var filters = [
            {
                'filterId': 1,
                'time': 'last 24 hours',
            },
            {
                'filterId': 2,
                'time': 'all',
            },
            {
                'filterId': 3,
                'time': 'last hour',
            },
            {
                'filterId': 4,
                'time': 'today',
            },
            {
                'filterId': 5,
                'time': 'yersteday',
            }
        ]; 


function selectFilter($scope) {

    $scope.items = ['filters'];
    $scope.selected = $scope.items[0];

    $scope.select= function(item) {
       $scope.selected = item; 
    };

}

Please, give me some help.

Thanks

0

4 Answers 4

72

The best solution would be to target it via angulars $index which is the objects index/position in the array;

HTML

<div ng-app='app' class="filters_ct" ng-controller="selectFilter">
    <ul>
        <li ng-repeat="filter in filters" ng-click="select($index)" ng-class="{sel: $index == selected}">
            <span class="filters_ct_status"></span>
            {{filter.time}}
        </li>
    </ul>
</div>

JS/Controller

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

app.controller('selectFilter', function($scope) {
var filters = [
            {
                'filterId': 1,
                'time': 'last 24 hours',
            },
            {
                'filterId': 2,
                'time': 'all',
            },
            {
                'filterId': 3,
                'time': 'last hour',
            },
            {
                'filterId': 4,
                'time': 'today',
            },
            {
                'filterId': 5,
                'time': 'yersteday',
            }
        ]; 

    $scope.filters = filters;
    $scope.selected = 0;

    $scope.select= function(index) {
       $scope.selected = index; 
    };
});

JSFIDDLE

Sign up to request clarification or add additional context in comments.

9 Comments

I'm trying to understand how it works, but i don't realize one thing, how you can change the style of a single element in the ng-click rather than change the style of everyone?
The click event is performed on one LI at a time and it's targeted by it's $index. So if you click on the first LI the index would be 0 and that's how it targets it. Hope that helps.
yes ok, but it's the expression in the ng-class that's not so clear to me, essentially is it a boolean and when it's true it gain the class sel?
Uep, so if the result from the expression on the ng-class directive is true then it sets the class sel on the LI and if not, it doesn't set it.
I wonder why this works: jsfiddle.net/f0mcLrxv (call function) but this not: jsfiddle.net/rseme7qn (set selected directly)
|
9

Slow to answer, here is what I got ( might add a little more )

WORKING DEMO : http://jsfiddle.net/WVY7L/

TEMPLATE

<ul>
    <li ng-repeat="filter in filters" 
       ng-click="select($index)" ng-class="{active: $index===selectedIndex}">
        <span class="filters_ct_status"></span>
        {{filter.time}}
    </li>
</ul>

CONTROLLER

$scope.filters = [
        { filterId: 1, time: 'last 24 hours'},
        { filterId: 2, time: 'all' },
        { filterId: 3, time: 'last hour'},
        { filterId: 4, time: 'today' },
        { filterId: 5, time: 'yersteday'}
    ]; 
$scope.selectedIndex = 0; /* first one set active by default */
$scope.select= function(i) {
  $scope.selectedIndex=i;
};
  • worth a mention that in the data you have trailing comma that should not be there.

     { filterId: 1, time: 'last 24 hours'**,**}
    

The rest was ensuring your controller was being passed the array number

ng-click="select($index)" ng-class="{active: $index===selectedIndex}"

and being able to save that array number selectedIndex for use in your template

$scope.selectedIndex

ng-class syntax

    {active: $index===selectedIndex}

Translates to add class with name of 'active' when the '$index' is equal to the 'selectedIndex'

1 Comment

great stuff, it is actually the same method as the accepted answer
2

I'm well late to the party, but this is the most reusable pattern, and it will save you re-writing the same function every time.

HTML:

<ul>
  <li ng-repeat="item in list" ng-click="setActive(item, list)" ng-class="{active: item.active}"></li>
</ul>

JS:

$scope.list = [{}, {}];

$scope.setActive = function(item, list){
  list.some(function(item){
    if(item.active){
      return item.active = false;
    }
  });
  item.active = true;
};

Comments

1

Test on the ID of the selected item :

<div class="filters_ct" ng-controller="selectFilter">
    <ul>
        <li ng-repeat="item in filters"  ng-click="select(item)" ng-class="{sel: item.filterId == selected.filterId}">
            <span class="filters_ct_status"></span>
            {{filters.time}}
        </li>
    </ul>
</div>

JS:

var filters = [
            {
                'filterId': 1,
                'time': 'last 24 hours',
            },
            {
                'filterId': 2,
                'time': 'all',
            },
            {
                'filterId': 3,
                'time': 'last hour',
            },
            {
                'filterId': 4,
                'time': 'today',
            },
            {
                'filterId': 5,
                'time': 'yersteday',
            }
        ]; 
    function selectFilter($scope) {

        $scope.filters = filters;
        $scope.selected = $scope.items[0];

        $scope.select= function(item) {
           $scope.selected = item; 
        };

    }

2 Comments

It doesn't work, i think the solution above is better, also thanks for your help
sorry i did not test the code, but what i wanted to point out here is that you must test on the attribute value ( item.filterId == selected.filterId ) instead of ( item == selected), anyway glad you found a solution.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.