【问题标题】:When Angular directive's name really matters当 Angular 指令的名称真的很重要时
【发布时间】:2014-01-05 13:24:25
【问题描述】:

我刚刚遇到 Angular 的一个奇怪行为:

场景如下:

在注册表单中,我想检查电子邮件的唯一性(通过对服务器的 http 调用)。
因此,我创建了一个名为 emailUnique 的指令,其客户端代码为:

<form name="form" novalidate>
<!-- some other fields -->
<input name="email" type="email" ng-model="user.email" required email-unique/>
</form>

对于帖子的其余部分,假设用户正在输入:michael,这显然不是有效的邮件。

让我们看看我的指令代码中有趣的部分,触发了我感兴趣的行为:

angular.module('directives.emailUnique', [])
    .directive('emailUnique', function () {
        return {
            restrict: 'A',
            require: 'ngModel',
            link: function (scope, el, attrs, ctrl) {
                ctrl.$parsers.push(function (viewValue) {
                    console.log(viewValue);   //What do you expect here for viewValue? answer below
                });
            }
        };
    });

在给出答案之前,乍一看,逻辑上的反应是:

undefined 

为什么?因为:

  • 我们精确到type="email" 属性,而不仅仅是type="text"
  • michael 不是有效的邮件。
  • Angular 的编译器应该符合经典的 HTML 行为。

经过测试,答案是undefined,符合预期。我的完整指令的逻辑将基于此,整个工作正常。

现在,让我们重命名指令:emailUnique 变为 somethingUnique。
现在的客户:

<input name="email" type="email" ng-model="user.email" required something-unique/>

惊喜:console.log(viewValue) 现在显示的是:michael,而不是 undefined ...

显然,在这种情况下,以email 开头的名称在处理电子邮件字段时会产生奇怪的效果。

我的问题很简单:有充分的理由吗?一个可能的错误?我可能会误解某些概念吗?

一些进一步的精度:

  • Angular's documentation about 带有角度的电子邮件字段不存在可能干扰email-unique 的某些email 属性。事实上,它基于type="email"
  • 无论表单的novalidate 属性是否存在,我都遇到了同样的问题。

【问题讨论】:

标签: javascript html forms angularjs angularjs-directive


【解决方案1】:

问题在于指令的优先级。由于您依赖于添加解析器的时间,因此您需要设置指令的优先级——这将确保您需要的时间。

在您的演示中,somethingUnique 指令在验证添加到解析器列表之前运行(它最终位于 3 个解析器的中间)。而emailUnique 是在之后添加的。

将指令的优先级设置为大于 0 可确保它在 emailValidation 始终为您提供undefined 后触发(注意$compile docs:“链接后功能以相反的顺序运行”)。要确认这一点,您可以通过将其优先级设置为小于 0 来强制 emailUnique 失败。

所以这解决了问题:

.directive('somethingUnique', function () {
    return {
        restrict: 'A',
        require: 'ngModel',
        priority: 100,
        link: function (scope, el, attrs, ctrl) {
            ctrl.$parsers.push(function (viewValue) {
                console.log(viewValue);
            });
        }
    };
});

Updated plunker

关于名称问题的更新: Angular 似乎按字母顺序处理具有相同优先级的指令。所以homethingUnique 的行为类似于emailUnique,因为两者都出现在input 之前,而jomehtingUnique 的行为类似于somethingUnique- 在输入之后运行。

但是Angular's docs 说:“具有相同优先级的指令的顺序是未定义的。”所以我们不能指望字母顺序。

【讨论】:

  • 太棒了。 “为什么这个名字在这里似乎很重要是一个我想深入研究的谜题” => 也很想知道原因。
  • 太好了,非常有趣:) 但是有一个问题:指令的priority 越高,它的解析器就越早运行,不是吗?如果我为 somethingUnique 设置 100,为什么它的相应解析器不在 emailValidation 之前运行,因为它会被第一个推送?假设 emailValidation 的默认值为 0。-
  • 关键是文档中的这一点:“预链接功能也按优先级顺序运行,但后链接功能按相反顺序运行”。这是一个更新,您可以在其中看到优先级 1 被添加,然后是优先级 100:plnkr.co/edit/0IFg5xMyDUtyMcB3hqTk?p=preview(请注意,我将范围传递给一个并将 viewValue 传递给另一个,以便您可以识别解析器链中的每一个)
  • 确实!非常感谢:)感谢这篇文章,我学到了很多东西。
猜你喜欢
  • 2021-11-30
  • 2018-05-31
  • 1970-01-01
  • 1970-01-01
  • 2016-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多