Adding class to an element on its click event

2019-03-14 01:15发布

问题:

I am new to Angular Js. I need to add a class to an element on its click event. I tried the following code. But it is not working.

<html>
<head>
    <style>
        .active{color:red;}
    </style>

    <script src="js/lib/jquery.min.js"></script>
    <script src="js/lib/angular.min.js"></script>
</head>
<body ng-app="MyApp" ng-controller="MyController">

    <div ng-repeat="data in datas">
        <p ng-click='selectMe()'>{{data.name}}</p>
    </div>

    <script>
    var app = angular.module('MyApp',[]);
    app.controller('MyController',function($scope){
         $scope.datas = [{name:"first"},{name:"second"}];

         $scope.selectMe = function (){
            $(this).addClass('active');
         }
    });

    </script>
</body>
</html>

What is the problem in this code? Is it necessary to use ng-class ? How to do it?

回答1:

You can pass $event to click

<p ng-click='selectMe($event)'>{{data.name}}</p>

//code:
$scope.selectMe = function (event){
   $(event.target).addClass('active');
}


回答2:

The Angular way (MVVM actually) to do this is to update the model through the click event and then paint according to the model, e.g.:

app.controller('MyController',function($scope){
    $scope.datas = [{name:"first", selected:false},{name:"second",selected:false}];
    $scope.selectMe = function(data) {
        var i;
        for( i=0; i < $scope.datas.length; i++ ) {
            $scope.datas[i].selected = false;
        }
        data.selected = true;
    };
}

And the HTML:

<div ng-repeat="data in datas">
    <p ng-click='selectMe(data)' ng-class="{selected: data.selected}>{{data.name}}</p>
</div>


回答3:

I know this question already has an answer, but I was shocked when I realized that the chosen best answer (which I had already implemented in some of my code) doesn't align with the AngularJS documentation.

According to AngularJS Documentation:

Do not use controllers to:

  • Manipulate DOM — Controllers should contain only business logic. Putting any presentation logic into Controllers significantly affects its testability. Angular has databinding for most cases and directives to encapsulate manual DOM manipulation.

huston007's answer works great, however, it does not follow this recommendation.

With this as your data input:

$scope.peeps = {
  '0': {
    'id': 0,
    'first_name': 'Tony',
    'last_name': 'Martin'
  },
  '1': {
    'id': 1,
    'first_name': 'Gerald',
    'last_name': 'Johanssen'
  },
  '2': {
    'id': 2,
    'first_name': 'Bobby',
    'last_name': 'Talksalot'
  }
};

And this your html:

<ul>
  <li ng-repeat="peep in peeps" 
      ng-click="addOrRemoveClassFromMe(peep.id)"
      ng-class="{selected: selectedPeeps[peep.id]}">
     {{peep.first_name}} {{peep.last_name}}
  </li>
</ul>

My suggested solution uses an array of objects with the person's id as the key and a booleon as the value. This is linked to in the DOM through the ngClass directive.

//-- create the selected peeps array
$scope.selectedPeeps = {};

//-- add the id to an array with a true-ey value
$scope.addOrRemoveClassFromMe = function(id) {

  //-- Set selected peeps as true/false
  if($scope.selectedPeeps[id]) {
    $scope.selectedPeeps[id] = false;
  } else {
    $scope.selectedPeeps[id] = true;
  }
};

You can check out my codepen here.

I also have another version that removes all of this logic from the controller, leaving only the variable definition, but I thought that might be out of the scope of this question. (codepen.io/joshwhatk/pen/bwmid)

Hope this helps.



回答4:

I know this is an old question but just came across it and think there's a simpler answer to any of the ones given here:

<div ng-repeat="data in datas">
    <p ng-click="active=!active"
       ng-class="{'active': active}">{{data.name}}</p>
</div>

No code needed in the controller other than to create your datas array. This works because the active variable is created within the child scope of each div created by the ng-repeat rather than in the controller's scope.

I've created an updated version of @joshwhatk's codepen here



回答5:

One of the best way is

<div ng-repeat="data in datas">
        <p ng-click="selectMe();clicked = true" ng-class="{active: clicked}" >{{data.name}}</p>
  </div>

Not required any code in controller

More Info