如果给定的指令是“终端”,如何要求优先级较低的指令?

时间:2014-06-30 17:55:09

标签: angularjs angularjs-directive

这是对https://stackoverflow.com/a/24058594/261673的跟进,我在其中询问如何制定一个为ng-options指令提供默认选项的指令。

我尝试提供默认值,以防ng-model定义的值未定义。

我已将require: 'ngModel'添加到指令选项,并将以下代码添加到link函数返回的compile函数中:

if(!$ctrl.$viewValue) { $ctrl.$setViewValue($scope.months[0]); }

其中$ctrlngModelController。如果我将优先级设置为0,那么可以正常工作(请参阅编辑),但是,如果我保留它原来的(1001)它不再有效。我怀疑这个指令是在ngModel之前编译的,因为它的terminal ngModel永远不会编译而且会中断。

有没有办法以某种方式使其工作而不将优先级更改为0?

这里有整个代码的Plunker:http://plnkr.co/edit/IZ0eyqHoqwSVPlhxI98X?p=preview

编辑:实际上,优先级0也不能正常工作。出于某种原因,每隔一次更改任何选择中的选项,该值将被取消定义,并且存在包含? undefined:undefined ??值的空选项...

2 个答案:

答案 0 :(得分:1)

我不知道为什么原来的回答者认为他们必须使用terminal: true,但你不必这样做。

所有你需要它来确保你的指令在select指令(在优先级0执行)之前编译,所以任何优先级> 0都会这样做(事实上使用优先级1工作正常)。

然后您可以照常访问所需指令的控制器:

app.directive('myOptionsMonths', function ($timeout) {
    return {
        priority: 1,
        require: 'ngModel',
        compile: function (tElem, tAttrs) {
            tAttrs.$set('ngOptions', 'month for month in months');
            tAttrs.$set('myOptionsMonths', null);
            return function (scope, elem, attrs, ctrl) {
                scope.months = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
                $timeout(function () {
                    if (ctrl.$viewValue === undefined) {
                        ctrl.$setViewValue(scope.months[0]);
                    }
                });
            };
        }
    };
});

<子> 您仍然需要使用$timeout,因为NgModelController的属性尚未设置


另请参阅此 short demo

答案 1 :(得分:0)

我已经弄明白了,然而,它看起来像是一个可怕的黑客。

查看$compileProvider.directive函数的源代码,我找到了一种在不使用ngModelController的情况下访问require: 'ngModel'的方法:

$timeout(function () {
  var ctrl = $element['data']('$ngModelController');

  if (ctrl.$viewValue) {
    ctrl.$setViewValue($scope.months[0]);
  }
});

它与之前的代码非常相似,但这次它可以通过编译元素访问ngModelController。需要$timeout,因为此时ctrl.$viewValue总是NaN,即使设置了模型值,也总是覆盖模型值。

这是更新的Plunker:http://plnkr.co/edit/h5ZPqTdyrZ0zTyyDcdei?p=preview