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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.