简体   繁体   English

为什么我的$ watch在指令测试中不起作用-Angular.js

[英]Why is my $watch not working in my directive test - Angularjs

I have a directive in which I pass in an attrs and then it is watched in the directive. 我有一个指令,在该指令中我传入了attrs ,然后在该指令中对其进行监视。 Once the attrs is changed, then an animation takes place. 一旦更改了attrs ,就会进行动画处理。 My attrs always is undefined when the $watch gets triggered. $watch触发时,我的attrs总是不确定的。

App.directive('resize', function($animate) {
  return function(scope, element, attrs) {
    scope.$watch(attrs.resize, function(newVal) {
      if(newVal) {
        $animate.addClass(element, 'span8');
      }
    });
  };
});

And here is my test: 这是我的测试:

describe('resize', function() {
  var element, scope;
  beforeEach(inject(function($compile, $rootScope) {
    var directive = angular.element('<div class="span12" resize="isHidden"></div>');
    element = $compile(directive)($rootScope);
    $rootScope.$digest();
    scope = $rootScope;
  }));

  it('should change to a span8 after resize', function() {
    expect($(element).hasClass('span12')).toBeTruthy();
    expect($(element).hasClass('span8')).toBeFalsy();
    element.attr('resize', 'true');
    element.scope().$apply();
    expect($(element).hasClass('span8')).toBeTruthy();
  });
});

When the attrs changes, my watchers newValue is undefined and so nothing happens. attrs更改时,我的观察者newValue是未定义的,因此什么也没有发生。 What do I need to do to make this work? 我需要做些什么才能使这项工作? Here is a plunker 这是一个矮人

You are not watching the value of attrs.resize ; 您没有在看attrs.resize的值; you are watching the value pointed by attrs.resize instead, in the test case a scope member called isHidden . 您正在查看attrs.resize 指向的值,在测试用例中,一个名为isHidden的范围成员。 This does not exist, thus the undefined . 这不存在,因此为undefined

For what you aare trying to do, the following would work: 对于您想尝试做的事情,以下方法将起作用:

App.directive('resize', function($animate) {
    return function(scope, element, attrs) {
        scope.$watch(
            // NOTE THE DIFFERENCE HERE
            function() {
                return element.attr("resize");
// EDIT: Changed in favor of line above...
//              return attrs.resize;
            },
            function(newVal) {
                if(newVal) {
                    $animate.addClass(element, 'span8');
                }
            }
        );
    };
});

EDIT: It seems that the attrs object does NOT get updated from DOM updates for non-interpolated values. 编辑:看来, attrs对象没有得到来自DOM更新更新的非插值。 So you will have to watch element.attr("resize") . 因此,您将不得不观看element.attr("resize") I fear this is not effective though... See forked plunk: http://plnkr.co/edit/iBNpha33e2Xw8CHgWmVx?p=preview 我担心这是行不通的……请参阅叉状塞子: http ://plnkr.co/edit/iBNpha33e2Xw8CHgWmVx? p= preview

Here is how I was able to make this test work. 这就是我使这项测试起作用的方式。 I am passing in a variable as an attr to the directive. 我将变量作为attr传递给指令。 The variable name is isHidden . 变量名称为isHidden Here is my test with the updated code that is working. 这是我对正在运行的更新代码的测试。

describe('resize', function() {
  var element, scope;
  beforeEach(inject(function($compile, $rootScope) {
    var directive = angular.element('<div class="span12" resize="isHidden"></div>');
    element = $compile(directive)($rootScope);
    $rootScope.$digest();
    scope = $rootScope;
  }));

  it('should change to a span8 after resize', function() {
    expect($(element).hasClass('span12')).toBeTruthy();
    expect($(element).hasClass('span8')).toBeFalsy();
    element.scope().isHidden = true;
    scope.$apply();
    expect($(element).hasClass('span8')).toBeTruthy();
  });
});

I am able to access the variable isHidden through the scope that is attached to the element . 我可以通过附加到element的作用域访问变量isHidden After I change the variable, the I have to run $digest to update and then all is golden. 更改变量后,必须运行$digest进行更新,然后一切正常。

I feel that I should probably be using $observe here as was noted by package . 我觉得我应该在这里使用$observe ,如package I will look at that and add a comment when I get it working. 我将对其进行研究,并在其起作用时添加评论。

As Nikos has pointed out the problem is that you're not watching the value of attrs.resize so what you can try doing is this: 正如Nikos指出的那样,问题在于您没有关注attrs.resize的值,因此您可以尝试执行以下操作:

Create a variable to hold your data and create these $watch functions: 创建一个变量来保存数据并创建以下$ watch函数:

var dataGetter;

scope.$watch(function () {
    return attrs.resize;
}, function (newVal) {
    dataGetter = $parse(newVal);
});

scope.$watch(function () {
    return dataGetter && dataGetter(scope);
}, function (newVal) {
    // Do stuff here         
});

What should happen here is that Angular's $parse function should evaluate attrs.resize and return a function like this . 这里应该发生的是Angular的$parse函数应该评估attrs.resize并返回类似this的函数。 Then you pass it the scope and do something. 然后,您将范围传递给它并执行某些操作。 As long as attrs.resize is just a boolean then newVal in the 2nd watch expression should be a boolean, I hope. 我希望,只要attrs.resize只是一个布尔值,那么第二个watch表达式中的newVal就应该是一个布尔值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM