我刚刚从Angular遇到一个奇怪的行为:
这是场景:
在注册表单中,我想检查电子邮件的唯一性(通过http调用服务器).
因此,我创建了一个名为emailUnique
其客户端代码的指令:
对于帖子的其余部分,让我们假设用户正在输入: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
.
客户现在:
惊喜:console.log(viewValue)
现在显示:michael
,而不是undefined
......
显然,email
在这种情况下,在处理电子邮件字段时,从名称开始会产生奇怪的效果.
我的问题很简单:有充分的理由吗?可能的错误?我可能会误解一些观念吗?
一些进一步的精确:
该角的文档有关的电子邮件场角不存在一些email
可能干扰属性email-unique
.实际上,它是基于type="email"
无论表单的novalidate
属性是否存在,我都遇到了同样的问题.
KayakDave.. 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); }); } }; });
更新了plunker
更新名称问题: Angular似乎按字母顺序处理具有相同优先级的指令.所以,homethingUnique
就像emailUnique
因为两者来之前input
,同时jomehtingUnique
表现得像somethingUnique
-输入后运行.
但是Angular的文档说:"具有相同优先级的指令的顺序是不确定的." 所以我们不能指望按字母顺序排列.
问题是指令的优先级.由于您依赖于添加解析器的时间,因此您需要设置指令的优先级 - 这将确保您需要的时间.
在您的演示中,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); }); } }; });
更新了plunker
更新名称问题: Angular似乎按字母顺序处理具有相同优先级的指令.所以,homethingUnique
就像emailUnique
因为两者来之前input
,同时jomehtingUnique
表现得像somethingUnique
-输入后运行.
但是Angular的文档说:"具有相同优先级的指令的顺序是不确定的." 所以我们不能指望按字母顺序排列.