我刚从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
不是有效邮件。经过测试后,答案为undefined
,符合预期。我的完整指令的逻辑将基于此,整体工作正常。
现在,让我们重命名指令:emailUnique
成为somethingUnique
客户现在:
<input name="email" type="email" ng-model="user.email" required something-unique/>
惊喜:console.log(viewValue)
现在显示:michael
,而非undefined
...
显然,在这种情况下,在处理电子邮件字段时,以email
开头的名称会产生奇怪的效果。
我的问题很简单:有充分的理由吗?可能的错误?我可能会误解一些观念吗?
进一步的准确性:
email
的某些email-unique
属性。实际上,它基于type="email"
novalidate
属性是否存在。答案 0 :(得分:5)
问题是指令的优先级。由于您依赖于添加解析器的时间,因此您需要设置指令的优先级 - 这将确保您需要的时间。
在您的演示中,somethingUnique
指令在验证添加到解析器列表之前运行(它最终在3个解析器的中间)。而emailUnique
之后又添加了undefined
。
将指令的优先级设置为大于0的值可确保它在emailValidation之后始终触发emailUnique
总是(从$compile docs注意到:“后链接函数以相反的顺序运行”)。要确认这一点,您可以通过将其优先级设置为小于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);
});
}
};
});
失败。
所以这解决了问题:
homethingUnique
更新名称问题:Angular似乎按字母顺序处理具有相同优先级的指令。因此,emailUnique
的行为与input
类似,因为它们都来自jomehtingUnique
而somethingUnique
的行为类似{{1}} - 在输入后运行。
但是Angular's docs说:“具有相同优先级的指令的顺序是未定义的。”所以我们不能指望按字母顺序排列。