简体   繁体   English

AngularJS:具有表单验证功能的动态输入

[英]AngularJS: Dynamic inputs with form validation

I'm creating inputs inside a form dynamically. 我在窗体内动态创建输入。 I created this directive for the purpose: 我创建此指令的目的是:

// Generate inputs on the fly using BE data.
.directive('inputGenerator', ['$compile', function ($compile) {
    return {
        restrict: 'E',
        scope: {
            id: '@',
            type: '@',
            name: '@',
            attributes: '=',
            ngModel: '=',
            ngDisabled: '='
        },
        link: function (scope, iElement, iAttrs) {
            // Get attributes
            var id         = iAttrs.id,
                type       = iAttrs.type,
                name       = iAttrs.name;

            scope.ngModel[name] = {};

            var extended_attributes = {
              "type": type,
              "id": id,
              "data-ng-model": 'ngModel.' + name + '[\'value\']',
              "name": name,
              "data-ng-disabled": "ngDisabled"
            };

            if ( ! scope.attributes) {
                scope.attributes = {};
            }

            // Append extra attributes to the object
            angular.extend(scope.attributes, extended_attributes);

            // Generate input
            var input = '<input ';

            angular.forEach(scope.attributes, function (value, key) {
                input += key + '="' + value + '" ';
            });

            input += '/>';

            // Compile input element using current scope (directive) variables
            var compiledElement = $compile(input)(scope);

            // Set the file selected name as the model value
            compiledElement.on('change', function () {
                if (this.files && this.files[0].name) {
                    var that = this;
                    scope.$apply(function () {
                        scope.ngModel[name] = {};
                        scope.ngModel[name]['value'] = that.files[0].name;
                    });
                }
            });

            // Replace directive element with generated input
            iElement.replaceWith(compiledElement);
        }
    };
}]);

This html line will trigger the directive: 此html行将触发指令:

<input-generator data-name="{{ item.name }}" data-ng-model="inputs.sources" data-attributes="item.attrs" data-type="{{ item.type }}" data-id="inputFile_{{ $index }}" data-ng-disabled="inputs.sources[item.name].selected" />

I'm running on Angular 1.4.3. 我正在Angular 1.4.3上运行。

Problem 问题

The model and pretty much everything works fine in the directive, but for some reason the form remains valid when the input added is invalid as you can see in this image. 该模型以及几乎所有内容都可以在指令中正常工作,但是由于某些原因,当添加的输入无效时,表单仍然有效,如您在此图中看到的。

在此处输入图片说明

I already tried: 我已经尝试过:

Any of the Angular features of form validation works 表单验证工作的任何Angular功能

I debugged Angular and seems to be that the input attached to the form is different from the input compiled inside the directive. 我调试了Angular,似乎连接到表单的输入与在指令内部编译的输入不同。

I already called formName.$setPristine() after each input was created, but it didn't work. 在创建每个输入之后,我已经调用了formName.$setPristine() ,但是它不起作用。

I couldn't access the form from the directive, but I think is not a good idea either. 我无法从指令访问表单,但我也不是一个好主意。

I already wrapped the input with a ng-form tag, but nothing useful comes out of that. 我已经用ng-form标记包装了输入,但是没有任何用处。

I tried to use the directive compile method, but this is just triggered once when the app loads and I've a select input that loads different inputs on change. 我尝试使用指令编译方法,但这只是在应用程序加载时触发一次,并且我有一个选择输入,它会在更改时加载不同的输入。

Any help on this is much appreciated! 任何帮助对此表示感谢! :) :)

Thank you to everyone for contribute anyways!! 谢谢大家的贡献!!

You should definitely take a look at my Angular-Validation Directive/Service . 您绝对应该看看我的Angular-Validation指令/服务 It as a ton of features and I also support dynamic inputs validation, you can also pass an isolated scope which helps if you want to not only have dynamic inputs but also have dynamic forms, also good to use inside a modal window. 它具有大量功能,并且我还支持动态输入验证,您还可以传递一个隔离的范围,如果您不仅希望具有动态输入而且还具有动态形式,并且还可以在模态窗口内使用,则可以提供帮助。

For example, let's take this example being a dynamic form and inputs defined in the Controller: 例如,让我们以该示例为动态表单和在Controller中定义的输入为例:

$scope.items.item1.fields = [
   {
      name: 'firstName',
      label:'Enter First Name',
      validation:"required"
    },
    {
      name: 'lastName',
      label: 'Enter Last Name',
      validation:"required"
    }
  ];
  $scope.items.item2 = {
    heading:"Item2",
    formName:"Form2"
  };
  $scope.items.item2.fields = [
   {
      name: 'email',
      label:'Enter Email Id',
      validation:"required"
    },
    {
      name: 'phoneNo',
      label: 'Enter Phone Number',
      validation:"required"
    }
];

It will bind the validation to the elements and if you want to easily check for the form validity directly from the Controller, simply use this 它将验证与元素绑定,如果您想直接从Controller轻松检查表单有效性,只需使用此

var myValidation = new validationService({ isolatedScope: $scope });

function saveData() {
    if(myValidation.checkFormValidity($scope.Form1)) {
        alert('all good');
    }
}

You can also use interpolation like so 您也可以像这样使用插值

<input class="form-control" type="text" name="if1"
        ng-model="vm.model.if1"
        validation="{{vm.isRequired}}" />

Or using a radio/checkbox to enable/disable a field that you still want to validate when it becomes enable: 或使用单选/复选框启用/禁用启用后仍要验证的字段:

ON <input type="radio" ng-model="vm.disableInput4" value="on" ng-init="vm.disableInput4 = 'on'">
OFF <input type="radio" ng-model="vm.disableInput4" value="off">

<input type="text" name="input4" 
        ng-model="vm.input4" 
        validation="alpha_dash|min_len:2|required" 
        ng-disabled="vm.disableInput4 == 'on'" />

It really as a lot of features, and is available on both Bower and NuGet (under the tag name of angular-validation-ghiscoding ). 它确实具有很多功能,并且可以在BowerNuGet (标记名称为angular-validation-ghiscoding )。 So please take a look at my library Angular-Validation and a live demo on PLUNKER . 因此,请看一下我的库Angular-ValidationPLUNKER上的实时演示。

It's loaded with features (custom Regex validators, AJAX remote validation, validation summary, alternate text errors, validation on the fly with the Service, etc...). 它具有许多功能(自定义Regex验证器,AJAX远程验证,验证摘要,替代文本错误,使用Service进行实时验证等)。 So make sure to check the Wiki Documentation as well... and finally, it's fully tested with Protractor (over 1500 assertions), so don't be afraid of using in production. 因此,请确保同时检查Wiki文档 ...最后,它已使用Protractor(超过1500个断言)进行了全面测试,因此不要害怕在生产中使用。

Please note that I am the author of this library 请注意,我是这个图书馆的作者

I ran into this issue as well with Angular v1.5.9. 我在Angular v1.5.9中也遇到了这个问题。 The main issue here is that you are compiling the HTML template before it is in the DOM, so Angular doesn't know it's part of the form. 这里的主要问题是您在将HTML模板放入DOM中之前就对其进行了编译,因此Angular不知道它是表单的一部分。 If you add the HTML first, then compile, Angular will see your input as a form child, and it will be used in the form validation. 如果先添加HTML,然后进行编译,Angular会将您的输入视为表单子项,并将其用于表单验证中。

See similar answer to Form Validation and fields added with $compile 看到与表单验证类似的答案以及$ compile添加的字段

Don't do: 不要做:

        var myCompiledString = $compile(myHtmlString)(scope);
        // ...
        element.replaceWith(myCompiledString);

Do this instead: 改为这样做:

        var myElement = angular.element(myHtmlString)
        element.replaceWith(myElement) // put in DOM
        $compile(myElement)(scope) // $compile after myElement in DOM

Note: I swapped the more conventional element for OP's iElement , which is a jQLite reference of the directive's HTML element 注意:我将更常规的element替换为OP的iElement ,这是指令的HTML元素的jQLite引用

you need to use ng-form directive as a wrapper for your input. 您需要使用ng-form指令作为输入的包装器。

you can see an example of this here 你可以在这里看到一个例子

but it works for me. 但这对我有用。 You can pass the form reference to the directive and use it directly. 您可以将表单引用传递给指令,然后直接使用它。

in the code below, the scope.form is used to know the general state of the form, and the scope.name to access the input field state. 在下面的代码中,scope.form用于了解表单的一般状态,而scope.name用于访问输入字段的状态。

< ng-form name="{{name}}" ng-class="{error: this[name][name].$invalid && form.$submitted}" > <ng-form name =“ {{name}}”“ ng-class =” {error:this [name] [name]。$ invalid && form。$ submitted}“>>

i hope it helps 我希望它会有所帮助

you need to set name of control dynamic and use this dynamic name for form validation. 您需要设置动态控件名称,并将此动态名称用于表单验证。 in the following eg you see the dynamic name and id of control and used for the validation of angular (using ng-massages) more details see http://www.advancesharp.com/blog/1208/dynamic-angular-forms-validation-in-ngrepeat-with-ngmessage-and-live-demo 在下面的示例中,例如,您将看到控件的动态名称和ID,并用于验证角度(使用ng-massages),更多详细信息,请参见http://www.advancesharp.com/blog/1208/dynamic-angular-forms-validation -in-ngrepeat与- ngmessage-和实时演示

Field Num Is Required. 必填字段。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM