ng-class within custom directive not observing updates

不想你离开。 提交于 2019-12-05 04:30:17

问题


I'm trying to create a directive that's used like this:

<amount value="myValue" neg-class="negative" />

myValue is a scope value (should be a number) negative is simply the name of a css class.

The idea behind the directive is that I wan't to show currency to the user and when the amount that's bound is negative, negClass get's applied to the rendered element.

The problem I'm having is that when negClass is changed, the update doesn't take effect. I do see the changes in the DOM, though.

Here's my directive definition:

myModule.directive('amount', function () {
    return {
        restrict: 'E',
        replace: true,
        template: '<span ng-class="{ {{negClass}}: value < 0 }">{{value | currency}}</span>',
        scope: {
            value: "=",
            negClass: "@",
        }

    };
});

Here's a test harness that demonstrates the problem: https://dl.dropboxusercontent.com/u/1563210/amtdirtest.html


回答1:


Most of the angular directives tend to work in this way. Unless the docs specifically mention supporting interpolation ({{...}}) for inputs then it's safer to not rely on it, especially where the input is an = rather than an @ binding.

In the case of ngClass, the attribute works like a = binding, and there is no mention of interpolation.

What actually happens in the directive is that the attribute is only observed in the linking phase and the the actual text in the attribute is never looked at again. So while the attribute continues to change, the changes are never seen.

By the time the attribute is seen by ngClass, it looks something like

{ n: value < 0 }

which is still evaluated based on whatever the current value is in scope, but the expression itself never gets changed again.

The safe way to do what you are trying would be to create an object without using interpolation, or to just have a function that returns which class is active...Something like the following should work:

myModule.directive('amount', function () {
    return {
        restrict: 'E',
        replace: true,
        template: '<span ng-class="getActiveClass()">{{value | currency}}</span>',
        scope: {
            value: "=",
            negClass: "@",
        },
        link: function(scope, element, attrs) {
            scope.getActiveClass = function() {
                if(scope.value < 0)
                    return scope.negClass;
            }
        }

    };
});



回答2:


Originally hadn't noticed that css was in the scope already.

Here's an approach that compiles the element dynamically using $compile and $watch to listen for changes in negClass

.directive('amount', function($compile) {
    var template='<span ng-class="{ {{negClass}}: value < 0 }">{{value | currency}}</span>'
    return {
      restrict: 'E',
      replace: true,
      scope: {
        value: "=",
        negClass: "@",
      },
      link:function(scope,elem,attrs){
        scope.$watch('negClass',function(){
          elem.html('').append($compile(template)(scope) )
        })

      }

    };
  });

DEMO



来源:https://stackoverflow.com/questions/20456057/ng-class-within-custom-directive-not-observing-updates

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!