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

时间:2013-12-17 16:49:26

标签: javascript html5 forms 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>

对于帖子的其余部分,我们假设用户输入了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关于带有角度的电子邮件字段不会显示可能会干扰email的某些email-unique属性。实际上,它基于type="email"
  • 我遇到了相同的问题,表单的novalidate属性是否存在。

1 个答案:

答案 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

Updated plunker

更新名称问题:Angular似乎按字母顺序处理具有相同优先级的指令。因此,emailUnique的行为与input类似,因为它们都来自jomehtingUniquesomethingUnique的行为类似{{1}} - 在输入后运行。

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

相关问题