"require" DDO Angular 指令的选项在应该抛出错误时没有抛出错误

"require" DDO option of Angular directive does not throw an error when it should

如果这很明显,请原谅我,但我只是在学习绳索。

我一直在关注 this article,试图理解 AngularJS 中的指令。

指令的 DDO 的 require 选项的 docs specify 如果未找到所引用的指令,则应抛出错误。

我似乎无法让它抛出错误 - 这是我的代码(我使用的是 v1.3.13)

test.html:

<body ng-app="Test">
    <dir />
</body>

test.js:

var test = angular.module('Test', []);

test.directive('dir', function() {
    return {
        require: '99 red baloons',
        restrict: 'E',
        template: '<div>this should not work</div'
    };
});

(这里是对应的jsfiddle)

一切似乎都工作正常,$compile 函数没有报错,指令被拾取并在 DOM 中呈现就很好了。我错过了什么?

谢谢!

编辑

这似乎是 Angular 中的错误,here's 要匹配的问题

所以这里存在几个问题,一个是代码,另一个(在我看来)是 angular 团队实现 Require 功能的不正确方式,我们需要解决这个问题。

为了使您的代码正常工作,您需要在 link 函数中引用所需的控制器,直到您这样做它才会检查控制器是否存在于先前的元素中并且不会抛出异常,另一个问题是您将需要在 linking api 的指令中构建所需的控制器才能工作。

不幸的是,angular 团队创建了默认行为,我不同意这种行为,即在指令的 compilation/rendering 阶段,当它确定需要什么时,它仍然会呈现 transcluded/template 有错误的指令。因此,即使应用程序抛出异常,它看起来也能正常工作。要解决此问题,您可以在成功加载后将子指令的 link 函数中的作用域 属性 设置为 true,您将在模板中的 ng-show 中使用它。如果 link 由于不满足所需的控制器而从未运行,则不会显示模板。

这是一个工作示例:

<body>
    <div main>
    </div>

    <script type="text/ng-template" id="main.html">
      <span>Hello, {{name}}!</span>
      <button ng-click="mainCtrl.log('Log Log Log, wondeful LOG!!!')">LOG</button>
      <sub></sub>
    </script>

    <script type="text/ng-template" id="sub.html">
      <div ng-show="loaded">{{name}} this should not work</div><div ng-transclude></div>
    </script>
</body>

与对应的javascript,只需将需要的控制器改成假名即可在控制台看到错误:

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

app.directive('main', function() {
  return {
    restrict: 'A',
    transclude: true,
    controllerAs: 'mainCtrl',
    controller: function($scope) {
      $scope.name = 'World';
      this.log = function(test) {
        console.log(test);
      };
    },
    templateUrl: 'main.html'
  }
});

app.directive('sub', function() {
  return {
    require: '^main',
    restrict: 'E',
    transclude: true,
    templateUrl: 'sub.html',
    link: function(scope, element, attrs, requiredCtrl) {
      requiredCtrl.log("heck ya!")
      scope.loaded = true;
    }
  };

});