AngularJS:带有表单验证的动态输入

时间:2015-07-30 15:02:55

标签: javascript angularjs forms validation directive

我正在动态创建表单内的输入。我为此目的创建了这个指令:

// 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);
        }
    };
}]);

此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" />

我正在使用Angular 1.4.3。

问题

模型和几乎一切都在指令中正常工作,但由于某种原因,当添加的输入无效时,表单仍然有效,如图所示。

enter image description here

我已经尝试过:

表单验证的任何Angular功能都可以使用

我调试了Angular,似乎附加到表单的输入与指令中编译的输入不同。

我在每个输入创建后都已调用formName.$setPristine(),但它不起作用。

我无法从指令中访问该表单,但我认为也不是一个好主意。

我已经用ng-form标签包装了输入,但没有任何用处。

我尝试使用指令编译方法,但这只是在应用程序加载时触发一次,并且我有一个选择输入,在更改时加载不同的输入。

对此有任何帮助非常感谢! :)

感谢大家的贡献!

5 个答案:

答案 0 :(得分:1)

你一定要看看我的Angular-Validation Directive/Service。它作为大量的功能,我也支持动态输入验证,你也可以传递一个隔离的范围,如果你不仅要有动态输入,还要有动态形式,这也有助于在模态窗口内使用。

例如,让我们将此示例作为动态表单和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"
    }
];

它会将验证绑定到元素上,如果您想直接从Controller中检查表单有效性,只需使用此

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

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

您也可以使用插值

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

或者使用收音机/复选框启用/禁用在启用时仍要验证的字段:

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'" />

它确实具有很多功能,可在BowerNuGet上使用(标记名为angular-validation-ghiscoding)。所以,请查看我的图书馆Angular-Validation以及 PLUNKER 的现场演示。

它已经加载了功能(自定义正则表达式验证器,AJAX远程验证,验证摘要,备用文本错误,使用服务即时验证等)。因此,请务必检查Wiki Documentation ......最后,使用量角器进行全面测试(超过1500个断言),所以不要害怕在生产中使用。

请注意我是这个图书馆的作者

答案 1 :(得分:1)

我和Angular v1.5.9一起遇到了这个问题。这里的主要问题是你正在编译HTML模板之前它在DOM中,因此Angular不知道它是表单的一部分。如果先添加HTML,然后编译,Angular会将您的输入视为表单子项,并将在表单验证中使用。

查看Form Validation and fields added with $compile

的类似答案

不要这样做:

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

请改为:

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

注意:我将更常规的element替换为OP的iElement,这是指令的HTML元素的jQLite引用

答案 2 :(得分:0)

您需要使用ng-form指令作为输入的包装。

您可以看到此here

的示例

答案 3 :(得分:0)

但它对我有用。您可以将表单引用传递给指令并直接使用它。

在下面的代码中,scope.form用于了解表单的一般状态,scope.name用于访问输入字段状态。

&LT; ng-form name =&#34; {{name}}&#34; ng-class =&#34; {error:this [name] [name]。$ invalid&amp;&amp;形式为$提交}&#34; &GT;

我希望它有所帮助

答案 4 :(得分:0)

您需要设置控件动态名称,并使用此动态名称进行表单验证。在以下例如你看到控制的动态名称和id,用于角度验证(使用ng-massages) 更多详情请参阅http://www.advancesharp.com/blog/1208/dynamic-angular-forms-validation-in-ngrepeat-with-ngmessage-and-live-demo

字段数是必需的。