3

I have a simple list item being parsed with ng-repeat:

<ul>
    <li ng-repeat="item in items" class="commonClass" ng-class="{'on': on_var}" ng-click="on_var=!on_var"> 
   {{item.name}} 
    <li>
</ul>

clicking on a list-item will add the class name 'on' as expected. but I want to remove all other 'on' classes as soon as you click on another list-item and only add it to the one clicked. I come from a jQuery background and I am new to angular. All I want to do is something like this:

$("li.commanClass").click(function(){ 
    $("li.commonClass").removeClass('on');
    $(this).addClass('on');
})

I want to know what is the "angular way" of achieving this result

jsfiddle

Thanks.

scniro
  • 16,844
  • 8
  • 62
  • 106
Sammy
  • 3,059
  • 4
  • 23
  • 32

4 Answers4

6

In angular you want to pass object references to child scopes as much as possible. This way you can use prototypical object inheritance that can branch down many levels.

Think of a scope as being a model. In the case of ng-repeat it creates a child scope for each element. So if the parent scope holds a model it will be passed as reference to the child scopes. Each of these child scopes will hold a reference to the parent scope model object.

Thus you can do:

<li ng-repeat="item in model.items" 
    ng-class="{'on': model.selected==item}" 
    ng-click="model.selected=item">{{ item.name }}</li> 

Then in controller:

$scope.model = {
        selected: null,
        items = [
            {name: "Apple"}, 
            {name: "Banana"}, 
            {name: "California"}
         ]
    };

Try to avoid using functions as above answer does. These functions will get called many times and will add unnecessary extra overhead.

Valuable post to read: "Thinking in AngularJS" if I have a jQuery background?

DEMO

Community
  • 1
  • 1
charlietfl
  • 170,828
  • 13
  • 121
  • 150
2

You can add a variable to your scope to maintain which item is selected, and a function on your scope that toggles the variable.

Controller:

app.controller('myCtrl', function($scope) {
    $scope.items = 
    [
        {name: "Apple"},
        {name: "Banana"},
        {name: "California"}
    ]

    $scope.selectItem = function( item ) {
        $scope.selectedItem = item;
    };
})

HTML:

<div ng-app="myApp">
    <ul ng-controller="myCtrl">
        <li ng-repeat="item in items" class="commonClass" ng-class="{'on': selectedItem === item}" ng-click="selectItem(item)">
            {{ item.name }}
        </li>
    </ul>
</div>
jsparks
  • 1,020
  • 1
  • 14
  • 19
1

Fiddle coming at ya of jsparks answer:

http://jsfiddle.net/eHDTF/

See fiddle for code!
chubbsondubs
  • 37,646
  • 24
  • 106
  • 138
0

I think you should refer a directive for whole your project instead of controller.

<div class="nav-item">
    <ul>
        <li active-me="on">Item 1</li>
        <li active-me="on">Item 2</li>
        <li active-me="on">Item 3</li>
        <li active-me="on">Item 4</li>
        <li active-me="on">Item 5</li>
    </ul>
</div>

Then create activeMe directive:

angular.module('app').directive('activeMe', function(){
    return {
        restrict: 'A',
        scope: {
            activeMe: '@'
        },
        link: function(scope, element, attrs) {
            element.bind('click', function() {
                if (scope.activeMe !== undefined && scope.activeMe.trim().length > 0) {
                    element.parent().children().removeClass(scope.activeMe);
                    element.addClass(scope.activeMe);
                } else {
                    element.parent().children().removeClass('active');
                    element.addClass('active');
                }
            });
        }
    };
});
Hieu Tran AGI
  • 849
  • 9
  • 9