“require”的Angular指令的DDO选项在应该的时候不会抛出错误

时间:2015-02-25 21:51:05

标签: javascript angularjs angularjs-directive require

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

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

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

我似乎无法让它抛出错误 - 这是我的代码(我正在使用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要匹配的问题

1 个答案:

答案 0 :(得分:5)

这里存在一些问题,一个是代码,另一个(在我看来)是一个错误的方式,角度团队已经实现了需要的功能,我们需要解决这个问题。

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

不幸的是,角度团队已经创建了默认行为,我不同意,在指令的编译/呈现阶段,当它确定需要什么时,它仍然会呈现出错的指令的transcluded / template 。因此即使应用程序抛出异常,它看起来仍然有效。为了解决这个问题,你可以在sub指令的link函数中将scoped属性设置为true,一旦成功加载,你将在模板中的ng-show中使用它。如果链接从未运行,因为不满足所需的控制器,则不会显示模板。

以下是一份工作样本:

<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;
    }
  };

});