Search code examples
angularjsmultidimensional-arrayindexofng-class

AngularJS ng-class check if nested key/value pair exists and then add value as class


So, I have this nested array which I can't modify the structure of. I want to check if a key/value pair exists and if it does, add a corresponding class to the element in question.

I have been trying to use a variation of the expression:

ng-class="{ 'active' : data.indexOf('"name":"john"') >= 0 }"

However my expression is a bit more complicated and I'm afraid it's too much to use just like that. There's also the problem of using more than two level nested quotes.

Here's a fiddle using an array with a similar structure to what I'm working with:

http://jsfiddle.net/5tvmL2Lg/2/

HTML:

<body ng-app="myModule">
<div ng-controller="myController">
  <div ng-repeat="hero in heroes">
    <div ng-class="{ 'weight-\'hero.stats.indexOf('\'type\':\'weight\'').value\'' : hero.stats.indexOf('\'type\':\'weight\'') >= 0 }">
            hello
     </div>
  </div>
</div>
</body>

JS:

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

myModule.controller('myController', ['$scope',  function($scope) {

    $scope.heroes = [{
      "firstname" : "clark",
      "lastname" : "kent",
        "stats" : [
        {
        "type" : "height",
        "value" : "6'2"
        },
        {
        "type" : "weight",
        "value" : 220
        },
        {
        "type" : "hair",
        "value" : "brown"
        }
      ]},
      {
      "firstname" : "bruce",
      "lastname" : "wayne",
        "stats" : [
        {
        "type" : "height",
        "value" : "6'1"
        },
        {
        "type" : "hair",
        "value" : "black"
        }
      ]},
      {
      "firstname" : "peter",
      "lastname" : "parker",
        "stats" : [
        {
        "type" : "height",
        "value" : "5'11"
        },
        {
        "type" : "weight",
        "value" : 180
        },
        {
        "type" : "hair",
        "value" : "auburn"
        }
      ]}];

}]);

In the end the goal would be to add a class named for example "weight-220" for the "clark kent" div, no class for the "bruce wayne" div, and "weight-180" for the peter parker div.

I know my problem is convoluted but any help would be greatly appreciated... :)


Solution

  • You don't need to add all your code logic into your ng-class. You can make it more complex (to check for the deeply-nested objects) by using a function that returns a string:

    <div ng-repeat="hero in heroes">
        <div ng-class="ClassBuilder(hero)">
            hello
        </div>
    </div>
    

    In your controller, add this function:

    $scope.ClassBuilder = function(hero) {
        for (var i = 0; i < hero.stats.length; i++) {
            if (hero.stats[i].type == "weight") {
                return "weight-" + hero.stats[i].value;
            }
        }
    }
    

    This will receive the hero object from each ng-repeat and check if the weight type exists. If so, it will use the corresponding value to return a string in your requested format, for example: "weight-220". Otherwise, it will return nothing and no class will be applied to that <div>.