Angularjs:由指令生成的输入字段的表单验证

时间:2014-08-18 14:58:28

标签: angularjs validation directive

我已经构建了一个基于meta($scope.meta)数据生成输入字段的指令。 我的问题是支持角度表单验证。

Plunkr:http://plnkr.co/edit/AfR5cWyywGlCECS6h6Dr?p=preview

说明:指令采用meta参数来描述它是什么输入字段类型以及用于呈现字段的其他相关信息。指令中定义的所有属性都将复制到元素,最后将在编译和链接后替换该指令。

查看:

<form name="userForm">
    <!-- Username -->
    <poly-field ng-model="storage" meta="meta" key="username" name="username" ng-minlength="3" ng-maxlength="8"></poly-field>
    <p ng-show="userForm.username.$error.minlength" class="help-block">Username is too short.</p>
    <p ng-show="userForm.username.$error.maxlength" class="help-block">Username too long</p>

    <!-- Email -->
    <poly-field ng-model="storage" meta="meta" key="email" name="email" ng-required></poly-field>
    <p ng-show="userForm.email.$error.minlength" class="help-block">Email is too short.</p>
    <p ng-show="userForm.email.$error.maxlength" class="help-block">Email is too long</p>
</form>

输入比允许的更长或更短的用户名应该会显示错误。 跳过电子邮件字段也显示错误。

以下是应用指令后的View源代码:

<form name="userForm" class="ng-pristine ng-valid ng-valid-required">
        <!-- Username -->
        <input type="undefined" ng-model="storage.username" meta="meta" key="username" name="username" ng-minlength="3" ng-maxlength="8" class="ng-scope ng-valid-minlength ng-dirty ng-valid ng-valid-maxlength">
        <p ng-show="userForm.username.$error.minlength" class="help-block ng-hide">Username is too short.</p>
        <p ng-show="userForm.username.$error.maxlength" class="help-block ng-hide">Username too long</p>

        <!-- Email -->
        <input type="undefined" ng-model="storage.email" meta="meta" key="email" name="email" ng-required="" class="ng-scope ng-valid ng-valid-required ng-dirty">
        <p ng-show="userForm.email.$error.minlength" class="help-block ng-hide">Email is too short.</p>
        <p ng-show="userForm.email.$error.maxlength" class="help-block ng-hide">Email is too long</p>
</form>

以下是视图和使用指令的模型,它在ParentCtrl中声明。

$scope.storage = {
    username: "Kitkat",
    email: "flying@kitkat.com"
};

这是元信息,它告诉输入字段是什么样的(是文本吗?日期等等)

 $scope.meta = {
    username: { type: "text" },
    email: { type: "text" }
};

指令声明:

app.directive('polyField', function($compile) {
    var linkFn = function(scope, element, attributes) {
        // create input element depending on the type
        var template = document.createElement("input");
        template.type = scope.storage[attributes.key].type;

        // copy all attributes
        for (var attr in attributes.$attr) {
            if (attributes.$attr[attr] == 'ng-model') {
                template.setAttribute('ng-model', attributes[attr] + '.' + attributes.key);
            } else {
                template.setAttribute(attributes.$attr[attr], attributes[attr]);
            }
        }

        // template compilation, linking and element replacement
        template = angular.element(template.outerHTML);
        var linkTemplate = $compile(template);
        var domElement = linkTemplate(scope);
        element.replaceWith(domElement);
    }

    var directive = {
        restrict: 'E',
        scope: { 
            meta: '=',
            storage: '=ngModel',
            key: '=',
        },
        link: linkFn
    };

    return directive;
  });

一些想法:
每个指令都创建一个隔离的范围,因此,在指令userForm内部是看不见的,但是,从指令的范围和父级中可以看到双向绑定的storage(ng-模型)范围,如果userForm看到storage里面的内容应该没问题,那不是吗?

我试图将userForm传递给指令范围:

// directive
scope: {
        meta: '=',
        storage: '=ngModel',
        key: '=',
        userForm: '='
}

// template
<poly-field user-form="userForm" ng-model="storage" meta="meta" key="username" name="username" ng-minlength="3" ng-maxlength="8"></poly-field>

但没有效果。

当我查看指令范围时,在userForm字段中,我看到输入字段实际上是$dirty: false$invalid: true,并且在我输入用户名/电子邮件字段后,< / p>

在源代码中,它似乎正确应用了验证类:         ng-valid-minlength ng-dirty ng-invalid ng-invalid-maxlength 仍然没有显示验证错误。

我能用它做什么吗?

1 个答案:

答案 0 :(得分:2)

为了让Angular的表单验证能够启动,ngModel在其控制器的实例化过程中查找父ngForm / form指令阶段(在预连接阶段之前)。

由于您在将元素添加到DOM之前编译并链接该元素,因此当时没有父元素,因此无法注册。

您只需要先将元素插入DOM,然后进行编译和链接。

<强> Updated plunkr