【问题标题】:stop execution of other directive on my custom element directive停止在我的自定义元素指令上执行其他指令
【发布时间】:2014-12-19 05:00:35
【问题描述】:

我有一个自定义元素指令,例如如下所示

  <my-wrapper ng-model="values.abc" unique-check="" list="list" prop="name"> </my-wrapper>

该指令确实需要 ng-model,稍后将在内部输入标签上设置它

  <input type="text" name="myfield" ng-model="'+attrs.ngModel+'"/>

发生的问题是当我检查控制台时,我可以看到指令上的 ng-model 与输入标签上的 ng-model 不同。

如何确保未创建外部标记上的 ng-model 并且它仅在我的指令中创建一次。

我的指令代码如下

app.directive("myWrapper", function(){

  var templateFn = function(element, attrs){
    return '<div ng-form="myform">'+
          '<input type="text" name="myfield" ng-model="'+attrs.ngModel+'"/>'+
          '<span>(inside directive) : isDuplicate:{{myform.myfield.$error.isDuplicate}}</span>'
          '</div>';
  }

  return {
    restrict :'E',
    template : templateFn,
    require: 'ngModel',
    scope: true
  }
});

请注意,以上只是我的指令的简化版本,我保留了 scope: true 因为整体场景的要求。

如果不清楚我在说什么,请查看THIS PLUNKER的控制台

我尝试了使用terminal : true 和/或priority : 1001 的解决方案,以便不会在指令html 上创建ng-model,而是仅在输入标签上创建ng-model,但它们都不起作用。

是的,一种解决方案是用指令上的 my-model 替换 ng-model,然后在输入标签上再次将其添加为 ng-model,但随后它在我的应用程序中的近 1000 个地方使用,所以真的不想这样替换它。

解决此问题的任何其他方法。

【问题讨论】:

  • 会不会是缺少&lt;/div&gt;? (长镜头,我知道...)还尝试将优先级设置为 0 以外的值。(priority: 0 是默认值,但是当最后一步发生时,链接函数中的时机很棘手,优先级是反向运行的。)如果你做了一个 plunker,它可能更容易调试。
  • 感谢您指出这一点,上面的代码只是一个人为的例子。将相应地更新问题...
  • 据我所知,不幸的是,您将不得不使用 my-model 选项。
  • @CorySilva 创建了 plunker...
  • 我对 Angular 真的很陌生,但试图弄清楚开发人员在堆栈世界中使用 Angular 所做的所有事情,并遇到了这个问题。不确定我是否正确理解了这个问题,但为什么我们不能只使用链接功能来删除属性?在删除它之前,只需保留该值。如果我错了,请告诉我。

标签: angularjs angularjs-directive


【解决方案1】:

所以try this plunker。基本上我让my-wrapper 指令通过它的简单属性传递到它的输入标签上。对于需要解析的属性,我只是简单的解析并注入到my-wrapper指令创建的作用域中。

我不太清楚为什么你有一个指令将表单包裹在单个输入周围,但就像你说的那样,这是一个人为的例子。就个人而言,我会改变这种结构,但我尽量不要太破坏性。

希望这会有所帮助。也许您可以解释一下您的意图。

【讨论】:

  • one solution can be to replace ng-model with lets say my-model on the directive and then again add it as ng-model on input tag 这个选项我知道,但只是想避免。关于每个控件一个表单,基于输入的内部指令可以有多个输入,在这个简单的例子中 - 我不想通过告诉非那么多需要知道的逻辑来混淆其他人
  • my-model 解决方案似乎比重组更容易。对于结构,为什么不只使用两个ng-repeat 指令:一个在表单数组上,第二个在输入/ng-models 上?
  • 它不仅仅是 ng-model,我将不得不为我的大多数基于包装器指令的自定义指令执行此操作。这对我来说就像一个巨大的 - 非常巨大的变化:(,但不幸的是,它似乎无法解决:(我真的不明白为什么终端/优先级的东西不起作用:(
  • FWIW 终端工作正常,但您的 uniqueCheck 指令出错,因为您告诉它需要 ngModel,但 terminal: true 专门停止创建 ngModel
  • 如果它停止执行 ng-model 指令,那么它也应该停止执行 uniqueCheck 指令
【解决方案2】:

您可以尝试使用嵌入。与其尝试突破标准 AngularJS 编译的困难部分,不如将结构更改为:

<my-wrapper>
    <input name="..." ng-model="...">
</my-wrapper>

并让您的指令将包装器扩展到您的模板中,并在其中包含嵌入的输入。 (请参阅$compile documentation 中的transclude 选项。)这也会增加模板的可读性。


或者,如果您需要您的指令生成复杂的内容(多个输入等),所有内容都被封装并绑定到单个 ng-model,您可以将 ng-model 保留在原处,并使您的指令完全封装。我的意思是这样的:

.directive('myComplexField', function () {
    return {
        scope: {},
        require: 'ngModel',
        link: function ($scope, $element, $attrs, ngModelCtrl) {
            ngModelCtrl.$formatters.push(function (modelValue) {
                // ... (update your isolated model based on external model change)
            });
            ngModelCtrl.$parsers.push(function (viewValue) {
                // ... (update external model based on your isolated model)
            });
            $scope.$watch('... (properties of your isolated model)', function () {
                // force sync (parser code above will take care of setting the real value)
                ngModelCtrl.$setViewValue(!ngModelCtrl.$viewValue);
            });
        }
    };
})

(请参阅ngModelController documentation)。您只需要注意不要在$parser$formatter 之间创建无限循环。


如果您真的不喜欢将ng-model 留在包装器上并使用priorityterminal 跳过它,那就是pretty simple

.directive('foo', function ($compile, $timeout) {
    return {
        restrict: 'E',
        priority: 2,  // ngModel priority is 1 (see the docs)
        terminal: true,
        link: function ($scope, $element) {
            $compile($element, undefined, 1)($scope);  // compiles priority *lower than 1*
        }
    };
}

应该尽可能避免这种方法,因为它有很多明显的缺点,没有真正的好处。

【讨论】:

  • 输入标签是动态生成的,所以不能使用transclude
  • 好的。除非我看到整个场景,否则我真的不能说,但我仍然建议进行干净的拆分。如果不是我建议的,那么相反(@CorySilva 在他的回答中建议) - 将模型表达式放入指令的配置中。
  • 我已经用第三种选择扩展了我的答案,这对于复杂的“一个模型的多个输入”逻辑很有用。
  • 对不起,但这也无济于事,我想了解终端和优先级的工作方式,或者更确切地说,为什么它们在这种情况下无法工作,我知道替代解决方案(其中很少有我已经在我的问题本身中提到过。)但我正在寻找可能的最佳解决方案,这似乎使用终端/优先级属性似乎是合理的,但唉,情况似乎并非如此
  • 那么答案很简单不,你不能用你选择的工具做你想做的事terminal(与 priority 一起使用)的目的是允许指令剪切其元素并稍后在将其插入某处时手动编译低级指令(想想ng-repeat)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-23
  • 1970-01-01
  • 2016-08-24
  • 1970-01-01
  • 2020-06-24
相关资源
最近更新 更多