从json创建动态表单期间出错,无法找到名称为"data"的控件 [英] Error during dynamic form creation from json Cannot find control with name: 'data'

查看:143
本文介绍了从json创建动态表单期间出错,无法找到名称为"data"的控件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用angular 7应用程序,并且正在编写一个通用的动态表单创建器.我正在使用反应式表单和ng-template and <ng-container *ngTemplateOutlet>递归显示表单元素.可以在此处看到代码.

I am using angular 7 appplication and i am writing a generic dynamic form creator. I am using reactive forms and ng-template and <ng-container *ngTemplateOutlet> for recursively displaying the form element.The code of the project could be seen Here.

但是我面临以下错误

ERROR Error: Cannot find control with name: 'data'
    at _throwError (forms.js:1775)
    at setUpControl (forms.js:1683)
    at FormGroupDirective.push../node_modules/@angular/forms/fesm5/forms.js.FormGroupDirective.addControl (forms.js:4532)
    at FormControlName.push../node_modules/@angular/forms/fesm5/forms.js.FormControlName._setUpControl (forms.js:5030)
    at FormControlName.push../node_modules/@angular/forms/fesm5/forms.js.FormControlName.ngOnChanges (forms.js:4980)
    at checkAndUpdateDirectiveInline (core.js:9239)
    at checkAndUpdateNodeInline (core.js:10507)
    at checkAndUpdateNode (core.js:10469)
    at debugCheckAndUpdateNode (core.js:11102)
    at debugCheckDirectivesFn (core.js:11062)

但是,如果我看到我的formGroup对象,则可以看到一个控件,其中的数据为控件的名称,如下所示.

But if i see my formGroup object i can see a control with data as the name of the control as shown below.

我在做什么错?请帮忙.

What is the mistake i am doing ? Please help.

问题的重现方式是在此处进行堆栈闪电

推荐答案

您正确的ng-template存在问题.

You're right there is a problem with ng-template here.

FormControlName指令在很大程度上取决于当前元素上方的元素层次结构来确定FormControl. 由于您使用的是ngTemplateOutlet,因此此层次结构混杂在一起,并且Angular找不到父FormGroupFormArray控件.

FormControlName directive heavily relies on hierarhy of elements above current element to determine FormControl. Since you're using ngTemplateOutlet this hierarhy mixed up and Angular can't find parent FormGroup or FormArray controls.

您可以重构示例以使用嵌套组件,并且如果您保留子级AbstractControls的层次结构,它应该可以工作.

You can refactor your example to use nested components and it should work if you will keep hierarhy of child AbstractControls.

另一方面,如果您要使用 FormControl ngTemplateOutlet一起使用>指令. 您只需要确保对input元素提供了正确的控制即可.

On the other hand, you can make it work with ngTemplateOutlet if you will use FormControl directive. You need to only make sure you provided correct control to your input element.

这是可以完成的方法:

<form [formGroup]="form">
    <ng-container *ngTemplateOutlet="controlList; context: {controls: schema, path: []}"></ng-container>

    <ng-template #controlList let-controls="controls" let-path="path" let-isArray="isArray">

        <ng-container *ngFor="let control of controls; let i = index;">
            <ng-container *ngIf="control?.type === 'simple'">
                <div class="control">
                    <label>
              {{ control.label }}
              <input type="text" [formControl]="form.get(isArray ? path.concat(i, control.name) : path.concat(control.name))"> 
            </label>
                </div>
            </ng-container>
            <ng-container *ngIf="['object', 'array'].indexOf(control.type) > -1">
                <fieldset>
          <legend>{{control.name}}</legend>
                    <ng-container
                        *ngTemplateOutlet="controlList; context: {controls: control.items, isArray: control.type === 'array', path: isArray ? path.concat(i, control.name) : path.concat(control.name)}">
                    </ng-container>
                </fieldset>
            </ng-container>
        </ng-container>

    </ng-template>
</form>

关键是要正确获取目标控件,而我将作为上下文的一部分传递给目标控件.

The key point here is to get correct path to destination control which I'm passing as part of context to next child level.

此外,如果要生成无限结构嵌套元素,则应重构代码以构建FormGroup:

Also if you want to generate infinity structure nested elements you should refactor your code for building FormGroup:

ngOnInit() {
  this.schema = data.start.fields.schema;
  this.form = this.createFormGroup(this.schema);
} 

createFormGroup(items) {
  let group: { [controlId: string]: AbstractControl; } = {};

  items.forEach((item) => group[item.name] = this.createFormControl(item));

  return this.fb.group(group);
}

createFormControl(item) {
  if (item.type === 'array') {
    return this.fb.array(item.items.map((subItem) => {
      return this.fb.group({
        [subItem.name]: this.createFormControl(subItem)
      })
    }));
  } else if (item.type === 'object') {
    return this.createFormGroup(item.items);
  } else {
    return this.fb.control(item.value, []);
  }
}

NG运行示例

Ng-run Example

这篇关于从json创建动态表单期间出错,无法找到名称为"data"的控件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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