当Angular指令的名称真的很重要时

Mik*_*378 6 javascript forms html5 angularjs angularjs-directive

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

这是场景:

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

<form name="form" novalidate>
<!-- some other fields -->
<input name="email" type="email" ng-model="user.email" required email-unique/>
</form>
Run Code Online (Sandbox Code Playgroud)

对于帖子的其余部分,让我们假设用户正在输入: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
                });
            }
        };
    });
Run Code Online (Sandbox Code Playgroud)

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

undefined 
Run Code Online (Sandbox Code Playgroud)

为什么?因为:

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

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

现在,让我们重命名指令:emailUnique成为somethingUnique.
客户现在:

<input name="email" type="email" ng-model="user.email" required something-unique/>
Run Code Online (Sandbox Code Playgroud)

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

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

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

一些进一步的精确:

  • 角的文档有关的电子邮件场角不存在一些email可能干扰属性email-unique.实际上,它是基于type="email"
  • 无论表单的novalidate属性是否存在,我都遇到了同样的问题.

Kay*_*ave 5

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

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

将指令的优先级设置为大于0的值确保它在emailValidation之后undefined始终触发(从$ compile文档中注意到:"post-link函数以相反的顺序运行").要确认这一点,您可以emailUnique通过将其优先级设置为小于0的值来强制失败.

所以这解决了这个问题:

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

更新了plunker

更新名称问题: Angular似乎按字母顺序处理具有相同优先级的指令.所以,homethingUnique就像emailUnique因为两者来之前input,同时jomehtingUnique表现得像somethingUnique-输入后运行.

但是Angular的文档说:"具有相同优先级的指令的顺序是不确定的." 所以我们不能指望按字母顺序排列.

  • 关键是来自文档的这一点:"预链接函数也按优先级顺序运行,但后链接函数以相反的顺序运行".这是一个更新,你可以看到优先级1加上优先级100:http://plnkr.co/edit/0IFg5xMyDUtyMcB3hqTk?p = preview(注意我将范围传递给一个,viewValue传递给另一个,这样你就可以识别每一个在解析器链中) (2认同)