AngularJS指令:为什么没有触发观察者?

时间:2014-02-16 11:28:29

标签: angularjs angularjs-directive angularjs-scope

LIVE DEMO

给出以下两个指令:

JS:

angular.module("Directives", []).directive("action", function($compile) {
  return {
    restrict: 'A',
    scope: {
      action: '='
    },
    link: function(scope, element) {
      scope.showDialog = false;

      var template = "<span dialog='showDialog'>Dialog</span>";

      element.append($compile(template)(scope)).on('click', function() {
        console.log("Setting showDialog to true");
        scope.showDialog = true;
      });
    }
  };
}).directive("dialog", function() {
  return {
    restrict: 'A',
    scope: {
      dialog: '='
    },
    link: function(scope, element) {
      element.hide();

      scope.$watch('dialog', function(newValue) {
        console.log("dialog changed to " + newValue); // Not called on button click
      });
    }
  };
});

HTML:

<button action>Click Here</button>

你能解释为什么设置action的{​​{1}}不会触发showDialog的观察者吗?

2 个答案:

答案 0 :(得分:2)

.on()是Angular的jqLit​​e中包含的jQuery方法。附加事件处理程序中的代码位于Angular之外,因此您需要使用$apply

  

$ apply()用于从外部执行角度表达式   角度框架。 (例如,来自浏览器DOM事件,   setTimeout,XHR或第三方库)。因为我们正在呼唤   我们需要执行适当范围生命周期的角度框架   异常处理,执行手表。

例如:

element.append($compile(template)(scope)).on('click', function() {
  scope.$apply(function () {  
    console.log("Toggling showDialog");
    scope.showDialog = !scope.showDialog;
  });
});

演示:http://jsbin.com/guziwamu/4/edit

答案 1 :(得分:0)

我对一种更常见的编写方式做了一些修改,我移动了element.hide(); $ watch注册后,它工作正常

app.directive("action", function ($compile) {
function link(scope, element, attrs) {      
    var template = "<span dialog='showDialog'>Dialog</span>";

    element.append($compile(template)(scope)).on('click', function () {
        console.log("Setting showDailog to true");
        scope.showDailog = !scope.showDailog;
    });
}

return {
    link: link
};  
});

app.directive("dialog", function ($compile) {
function link(scope, element, attrs) {

    scope.$watch(attrs.dialog, function (newValue) {            
        console.log("dialog changed to " + newValue); // Not called on button click
    });

    element.hide();
}

return {
    link: link
};
});

控制器:

app.controller('MyController', function ($scope) {

$scope.showDailog = false;
});

App JS:

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

HTML:

<button action>Click Here</button>
        Show dialog: <input data-ng-model="showDailog">