0

I have an app where I am running ng-repeat to display information. I need to then add classes to some of the generated elements after an Ajax call has been made.

I could do this easily with jQuery but I'm trying to stick to Angular/jqlite.

The problem I'm having is that I can get the element, but not as an object that addClass works on.

Here's what I've got so far:

angular.forEach($(".tile"), function(tile){
    if(srv.free.indexOf(angular.element(tile.querySelector('.label')).text()) != -1){
       tile.addClass("free");
    }
});

The array srv.free contains a list of names, those name values are the same as the text value of the div with class .label, which is inside of .tile. So I need to loop through each .tile, check the text value of the child .label and if that text value is in the array srv.free, add the class .free to .tile.

The point I'm at, is that addClass is "undefined" because at this point, tile is just a string, not a jquery/jqlite object.

How do I add a class to that, or get to the object version?

Update

I have previously tried to use ng-class on the elements to update the class, but could not get them to update.

I have a service that has free in it, which is initially set to a blank array. After an Ajax call:

$http.get('/json/free.json').success(function(data){
        srv.free = data;
});

Then, in my controller I have:

$scope.gsrv = globalService;

and in my ng-repeat:

<div class="col-xs-3 col-md-2" ng-repeat="Tile in list.tiles">
        <div class="tile" id="{{$index}}" ng-class="{free:$.inArray(Tile.Name, gsrv.free)}" ng-click="main.changeView('/Tile/'+$index)">
        <img src="http://placehold.it/256" ng-src="{{Tile.Icon}}" ng-class="{dis:!Tile.Stats}">
        <div class="label">{{Tile.Name}}</div>
    </div>
</div>

When that didn't work, I tried adding:

$scope.gsrv.free = globalService.free;

which did not change anything.

2
  • 1
    user ng-class on the element in the view. Commented May 20, 2015 at 6:53
  • I once heard, what also applies here, if you are using jQuery in your controllers, you do something wrong (following guidelines of using angular) Commented May 20, 2015 at 6:54

2 Answers 2

4

You state that the elemens are rendered in an ng-repeat. Therefore you can just use the ng-class directive to add a class based on some variable, something like the following:

<div ng-repeat="tile in tiles" 
     ng-class="{ free: tile.someVariable }"> // <-- adds a class 'free' when someVariable verifies to true
    <label>{{ tile.someVariable }}</label>
</div>

UPDATE

You can add those variables to the tiles, after the ajax call:

$http.get('/json/free.json').success(function(data){
    setTilesFree(data);
});

var setTilesFree = function (free) {
    var tiles = $scope.list.tiles; // shortcut
    for (var i = 0; i < tiles.length; i++) {
        // If in 'free' array, set tile free = true
        // This will update the DOM from this tile, adding the class 'free'
        if (free.indexOf(tiles[i].Name) > -1) {
            tiles[i].free = true;
        } else {
            tiles[i].free = false;
        }
    }
}

Then in your view:

<div ng-repeat="Tile in list.tiles">
    <div ng-class="{free: Tile.free}">
        <img src="http://placehold.it/256" ng-src="{{Tile.Icon}}" ng-class="{dis:!Tile.Stats}">
        <div class="label">{{Tile.Name}}</div>
    </div>
</div>

See this jsfiddle

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

6 Comments

Yes, but since the array I am checking against is populate via an Ajax call, the elements are pre-populated before the array has any content.
That shouldn't matter, when you do the ajax call and assign the data to the tiles variable, angular catches this and updates the DOM according
Then I'm doing that part wrong, because it's not updating for me. I have a service that is holding some information, including the array. When it updates the ng-class does not work...
Then please include how you are assigning your data to the tiles variable
Updated my question with info on my ng-repeat /ng-class
|
0

You can return empty array from list and free services and populate them later. Since Angular runs digest cycle after every $http.get, $scope will be properly updated and binding will work as expected. The most tricky thing is to populate the same existing array (initially returned by service) instead of creating new one every time. This is required, because controller function will not run again every time digest is running and therefore new array instance will not be assigned to the $scope. Here is on of the possible solutions:

JavaScript

angular.module('app',[]).
    factory('list', ['$http', function($http) {
      var tiles = [];
      return {
        getList: function() {
          if(!tiles.length) {
            $http.get('data.json').then(function(res) {
              res.data.forEach(function(item) {
                tiles.push(item);
              });
            });
          }
          return {
            tiles: tiles
          };
        }
      }
    }]).
    factory('free', ['$http', function($http) {
      var free = [];
      return {
        getFree: function() {
          if(!free.length) {
            $http.get('free.json').then(function(res) {
              res.data.forEach(function(item) {
                free.push(item);
              });
            });
          }
          return free;
        }
      }
    }]).
    controller('ctrl', ['$scope', 'list', 'free', function($scope, list, free){
      $scope.list = list.getList();
      $scope.free = free.getFree();
    }]);

HTML

<div class="col-xs-3 col-md-2" ng-repeat="Tile in list.tiles">
    <div class="tile" ng-class="{free: free.indexOf(Tile.Name) > -1}">
        <img ng-src="{{Tile.Icon}}" ng-class="{dis:!Tile.Stats}">
        <div class="label">{{Tile.Name}}</div>
    </div>
</div>

Plunker

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

Update:

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

(the same example with static pre-populated list, and also service instead of factory)

2 Comments

List is a static, pre populated JSON object that is included on page load. I then create free as an empty array in my service. However once I update that same variable via $http, the ng-class doesn't update. Running a console.log shows the variable being updated.
@sharf In code snippet you provided srv.free = data; makes an issue, since with this assignment you replace one instance of empty array with another instance of array which is not watched by Angular. You should use srv.free.push(...) to put all the received data into the same instance of array hold by srv.free.

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.