ng-class is not applied on element with ng-repeat

846 views Asked by At

I have the following custom directive:

angular.module('Interfaces').directive('Interfaces', function() {
  return {
    restrict : 'A',
    scope : {
      minor : '@'
    },
    templateUrl : 'interfaces/interfaces.template.html',
    controller : [ '$scope', 'InterfacesService', function InterfaceController($scope, InterfacesService) {
      $scope.interfacesService = InterfacesService;
      $scope.label = 'Interfaces';
      $scope.optional = ($scope.minor == "true");
      if ($scope.optional) {
        $scope.label = '';
      }

      $scope.getInterfaces = function getInterfaces() {
        return $scope.interfacesService.getInterfaces($scope.minor);
      };
    } ]
  };
});

And the following template

<tr ng-class="{'optional': optional}"><td colspan="5">Just testing</td></tr>
<tr ng-class="{'optional': optional}" ng-repeat="interface in interfaces = (getInterfaces())" >
  <td rowspan='{{interfaces.length}}' class='label-column' ng-if="$index === 0">{{label}}</td>
  <td colspan='2' class='data'>{{interface.key}}</td>
  <td colspan='2' class='data'>{{interface.value}}</td>
</tr> 

I am using this directive as part of a table:

<table>
  <tbody>
    <!-- other table content -->
  </tbody>
  <tbody interfaces minor="true"></tbody>
  <tbody interfaces minor="false"></tbody>
  <tbody>
    <!-- other table content -->
  </tbody>
</table>

The first table row is just added for testing purposes. It correctly has the class "optional" according to the value of the variable 'optional'. However, those table rows created by ng-repeat never have the "optional" class set, no mattter what the value of the 'optional' variable.

I have found the following article Angular js Custom Directive on element with ng-repeat - Can't set CSS classes which suggests using a priority of -1001 in my directive, but neither the 1001 of the original code in that post nor the -1001 suggested in the answer make a difference in my case.

Why is ng-class not applied on the element with the ng-repeat?

1

There are 1 answers

0
Urs Beeli On

Ok, after talking to a friend it seems the problem was the following line in the template:

<tr ng-class="{'optional': optional}" ng-repeat="interface in interfaces = (getInterfaces())" >

Having put the getInterfaces() call in brackets seems to have lead to an endless iteration which stopped the ng-class from being applied. I had seen those error messages but did not make the connection between them and my issue.

I have solved the issue as follows:

Instead of retrieving the data from the InterfacesService, I am now passing them from the outer template as a parameter:

<tbody interfaces minor="true" interfaces="{{information.host.interfaces}}"></tbody>
<tbody interfaces minor="false" interfaces="{{information.host.interfaces}}"></tbody>

And in the directive I've added a new binding:

 scope : {
      minor : '@',
      interfaces: '<'
    },

And my interface template now directly references this new binding:

<tr ng-class="{'optional': optional}" ng-repeat="interface in interfaces" >

The reason for attempting to get this information from the InterfacesService instead of passing it into the directive was that I had tried that and failed, using the service had been a workaround.

I stumbled across the same problem again in a slightly different setting (see AngularJs: How to pass part of my data from one component to another) and the answer there (to use a '<' binding instead of '@' allowed me to get rid of the service and hence the

 (getInterfaces())

part of my ng-repeat statement.