Deiwin
Deiwin

Reputation: 447

Linking a data-bound HTML class to a directive

So basically I want to have classes "order-asc" and "order-desc" be toggled on a directive. I've scrapped the toggling part for now.

I have the following test:

describe('OfferList sorters', function() {
  'use strict';
  beforeEach(module('offerListSorters'));

  describe('sorter directive', function() {
    var element, scope, parentScope;
    beforeEach(inject(function ($compile, $rootScope){
      parentScope = $rootScope.$new();
      element = angular.element('<sorter order-by="location">{{2+2}}</sorter>');
      $compile(element)(parentScope);
      scope = element.isolateScope();
      parentScope.$digest();
    }));

    it('should contain 4', function() {
      expect(element.html()).toBe('4');
    });

    it('should have asc/desc state on scope', function(){
      expect(scope.isAscending).toBeDefined();
    });

    it('should have class order-asc by default', function() {
      expect(element).toHaveClass('order-asc');
    });
  });
});

I have the following directive:

offerListSorters.directive('sorter', [function (){
  return {
    scope: {},
    controller: function($scope, $element, $attrs, $transclude) {
      $scope.isAscending = true;
    },
    link: function($scope, iElm, iAttrs, controller) {
      iElm.addClass('order-{{isAscending ? \'asc\' : \'desc\'}}');
    }
  };
}]);

I find that the last test fails. The {{}} binding gets added to the class attribute verbatim. I've also tried the following lines in the directives link function with no results:

iElm.attr('ng-class', 'isAscending ? \'asc\' : \'desc\'');
iAttrs.$set('ngClass', 'isAscending ? \'asc\' : \'desc\'');

I've tried adding $scope.$digest(); to the end of link function. But I've gotten nowhere.

I could solve it as it was done here or by doing some $scope.$watch magic in the link function, but I'd really like to understand why what I'm currently trying is not working.

Upvotes: 0

Views: 57

Answers (1)

Narretz
Narretz

Reputation: 4993

Why don't you just use ng-class?

<div sorter ng-class="{'asc' : isAscending, 'desc' : !isAscending}"></sorter>

Adding the binding inside addClass etc. isn't going to work because the binding logic is added during the $compile pahse when angular uses $interpolate and $parse to detect bindings / directives in the DOM / templates. When you add it afterwards, angular treats it as normal string.

Upvotes: 1

Related Questions