AngularJS:带有表单验证的动态输入 [英] AngularJS: Dynamic inputs with form validation

查看:157
本文介绍了AngularJS:带有表单验证的动态输入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  //使用BE数据即时生成输入。 
.directive('inputGenerator',['$ compile',function($ compile){
return {
restrict:'E',
scope:{
id:'@',
类型:'@',
名称:'@',
属性:'=',
ngModel:'=',
ngDisabled:'='
},
link:function(scope,iElement,iAttrs){
//获取属性
var id = iAttrs.id,
type = iAttrs.type,
name = iAttrs.name;

scope.ngModel [name] = {};

var extended_attributes = {
类型:类型,
id:id,
data-ng-model:'ngModel。'+ name +'[\'value \'''',
name:name,
data-ng-disabled:ngDisabled
};

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

//将附加属性追加到对象
angular.extend(scope.attributes,extended_attributes);

//生成输入
var input ='< input';

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

input + ='/>';

//使用当前范围(指令)变量编译输入元素
var compiledElement = $ compile(input)(scope);

//将文件选择名称设置为模型值
compiledElement.on('change',function(){
if(this.files&& this。文件[0] .name){
var that = this;
scope。$ apply(function(){
scope.ngModel [name] = {};
scope。 ngModel [name] ['value'] = that.files [0] .name;
});
}
});

//将指令元素替换为生成的输入
iElement.replaceWith(compiledElement);
}
};
}]);

这个html行会触发指令:

 < input-generator data-name ={{item.name}}data-ng-model =inputs.sourcesdata-attributes =item.attrsdata -type ={{item.type}}data-id =inputFile _ {{$ index}}data-ng-disabled =inputs.sources [item.name] .selected/> 

我在Angular 1.4.3上运行。



模型和几乎所有的指令都可以正常工作,但由于某些原因,输入在输入时仍然有效添加无效,你可以在这张图片中看到。







表单验证的任何Angular功能



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



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

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



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



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



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



感谢大家的贡献!

解决方案

我遇到了这个问题以及Angular v1.5.9。这里的主要问题是,在之前编译HTML模板,因此Angular不知道它是表单的一部分。如果您先添加HTML,然后进行编译,Angular会将您的输入看作表单验证。



请参阅与< a href =https://stackoverflow.com/a/21732008/1799146>表单验证和添加了$编译的字段



Don 't do:

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

改为:


$ b (myElement)(范围):$ b

  var myElement = angular.element(myHtmlString)
element.replaceWith(myElement)//放入DOM
$ compile(myElement) // $在myElement之后的DOM中编译

注意:我将更传统的元素用于OP的 iElement ,它是该指令的HTML元素的jQLite引用


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:

<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.

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

I debugged Angular and seems to be that the input attached to the form is different from the input compiled inside the directive.

I already called formName.$setPristine() after each input was created, but it didn't work.

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.

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!!

解决方案

I ran into this issue as well with 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. 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.

See similar answer to Form Validation and fields added with $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

这篇关于AngularJS:带有表单验证的动态输入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆