Angular 带有动态生成的输入字段的指令无法显示验证

Angular Directive with dynamically generated input fields not able to display validation

在搜索 Whosebug 和其他站点 3 天之后,我发现自己回到了原点。

我的任务:我需要验证动态生成的表单域。

HTML:

 <form name="myForm">
    <form-field content="field" model="output[field.uniqueId]" ng-repeat="field in formFields"></form-field>
 </form>

控制器:

var myApp = angular.module('myApp',[]);

function MyCtrl($scope) {
$scope.formFields = [
    {
    "fieldName": "Your Name",
    "uniqueId": "your_name_0",
    "fieldType": "text",
    "isMandatory": true
    },
    {
    "fieldName": "Description",
    "uniqueId": "description_1",
    "fieldType": "textarea",
    "isMandatory": true,
    }
];

$scope.output={};
}

指令:

myApp.directive("formField",function($compile){
var templates = {
    textTemplate:'<div class="form-group"><label for="{{content.uniqueId}}" >{{content.fieldName}}</label> <span ng-show="content.isMandatory" class="sub_reqText">*</span><span ng-show="form.content.fieldName.$invalid">Please check this field.</span><input type="text" ng-model="model" name="{{content.uniqueId}}" class="form-control" ng-required="content.isMandatory" id="{{content.uniqueId}}"/> </div><br>',
    textareaTemplate:'<div class="form-group"><label for="{{content.uniqueId}}" >{{content.fieldName}}</label> <span ng-show="content.isMandatory" class="sub_reqText">*</span> <span ng-show="form.content.fieldName.$invalid">Please check this field.</span> <textarea ng-model="model" name="{{content.uniqueId}}" id="{{content.uniqueId}}"  class="form-control" ng-required="content.isMandatory"></textarea> </div>' 
};

var getTemplate = function(content, attrs){
    var template = {};
    template = templates[content.fieldType+"Template"];
    if(typeof template != 'undefined' && template != null) {
            return template;
        }
        else {
            return '';
        }
};


var linker = function(scope, element, attrs){        
    element.html(getTemplate(scope.content, attrs)).show();        
    $compile(element.contents())(scope);
}

return {
    restrict:"E",        
    replace:true,        
    link:linker,
    scope:{
        content:'=',
        model:'=?'
    }
};
});

显然存在一些范围问题,因为我无法访问指令外的表单字段,也无法访问指令内的表单名称。我也知道 $scope.myForm.name 属性 不能是 angular 绑定表达式,但我不确定如何重写它以使其工作。

这是 jsfiddle:http://jsfiddle.net/scheedalla/57tt04ch/

任何指导都会非常有用,谢谢!

在调试问题时我发现,name 属性没有为表单正确编译。它在名称中显示 {{content.uniqueId}} 但实际上它在 UI.

上正确呈现

例如。 对于以下 html.

<input type="text" ng-model="model" name="{{content.uniqueId}}" class="form-control" 
ng-required="content.isMandatory" id="{{content.uniqueId}}"/>

name 呈现为 name="your_name_0" 但在表单集合中它显示 {{content.uniqueId}} 与插值指令。

名称似乎没有正确插入。

然后找到issue和AngularJS,"You can't set name attribute dynamically for form validation."

Note: Above mentioned issue has been fixed in Angular 1.3.(name attributes interpolates properly)

& 如果你想在 ng-repeat 中使用它们,那么你应该始终使用嵌套 ng-formng-repeat 内的成员将拥有自己的表单,使用该内部表单您可以处理验证。 Link For Reference

代码更改

var templates = {
        textTemplate: '<ng-form name="form">'+
    '<div class="form-group">'+
        '<label for="{{content.uniqueId}}">{{content.fieldName}}</label> '+
          '<span ng-show="content.isMandatory" class="sub_reqText">*</span>'+
          '<span ng-show="form.input.$invalid">'+
          'Please check this field.'+
          '</span>'+
        '<input type="text" ng-model="model1" name="input" class="form-control" ng-required="content.isMandatory" id="{{content.uniqueId}}" /> '+
    '</div>'+
'</ng-form>'+
'<br>',
        textareaTemplate: '<ng-form name="form">'+
    '<div class="form-group">'+
        '<label for="{{content.uniqueId}}">{{content.fieldName}}</label>'+
          '<span ng-show="content.isMandatory" class="sub_reqText">*</span> '+
          '<span ng-show="form.textarea.$invalid">Please check this field.</span>'+
          '<textarea ng-model="model" name="textarea" id="{{content.uniqueId}}" class="form-control" ng-required="content.isMandatory"></textarea>'+
    '</div>'+
'</ng-form>'
    };

只有我更改了模板html,基本上为模板添加了<ng-form></ng-form>并在内部形式的基础上处理了验证。

这是你的Working Fiddle

希望这已经清除了您的理解。谢谢。