指令隔离范围不触发$ watch

时间:2014-11-13 20:06:22

标签: angularjs angularjs-directive angularjs-scope

我有一个与其控制器共享数据的指令,我正在使用隔离范围。

但是,当我从指令内部更新数据时,指令和控制器都不会使用$ watch查看数据更改。

以下是我尝试做的一个例子:

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

app.controller('myAppCtrl', function($scope) {
  $scope.buttonSettings = {
    val: 0
  }

  $scope.$watch('buttonSettings.val', function(val) {
    console.log('watchInController')
    console.log(val)
  });
});

app.directive('buttonTest', function() {
  return {
    restrict: 'E',
    scope: {
      buttonSettings: '='
    },
    template: '<button>{{buttonSettings.val}}</button>',
    link: function(scope) {
      var button = $('button');

      console.log(scope.buttonSettings)

      scope.$watch('buttonSettings.val', function(val) {
        console.log('watchInDirective')
        console.log(val)
      });

      button.bind('mouseover', function() {
        scope.buttonSettings.val++;
        console.log('mouseover')
        console.log(scope.buttonSettings.val)
      })
    }
  }
});

以下是plunkr中的完整示例:http://plnkr.co/edit/lnztoMhtU03Qzl0BaMpk?p=preview

我做错了什么?

2 个答案:

答案 0 :(得分:1)

首先,你不应该这样使用jQuery。您可以使用元素参数将其注入指令,而不是使用jQuery选择按钮。

其次,您需要使用 $ scope。$ apply 来触发指令和控制器中的监视。

app.directive('buttonTest', function() {
  return {
    scope: {
      buttonSettings: '='
    },
    link: function(scope, element) {
      element.bind('mouseover', function() {
        scope.$apply(function() {
          scope.buttonSettings.val++;
        });
      })
    }
  }
});

查看此工作plunker

答案 1 :(得分:1)

halilb是正确的,你不应该使用jQuery来选择元素,而是使用Angular为你的指令提供的元素,并且需要$scope.$apply来注册在Angular的上下文之外发生的事件。但是,您根本不需要制定新的指令来解决您的问题。只需使用Angular的ngMouseover指令。您可以将函数绑定到它或直接添加逻辑。这是一个非常简单的例子。

<div ng-init="foo = 1">Value: {{foo}}</div>
<button ng-mouseover="foo = foo+1">Mouse over this: {{foo}}</button>

以下是移动到控制器的逻辑看起来相同的代码:

<div>Value: {{foo}}</div>
<button ng-mouseover="incrementFoo()">Mouse over this: {{foo}}</button>

控制器:

$scope.foo = 1;
$scope.incrementFoo = function() {
  ++$scope.foo;
};

Live demo