【问题标题】:Recursive Component of Dynamic Angular Forms - ERROR Error: Cannot find control with name:动态角度表单的递归组件 - 错误错误:找不到具有名称的控件:
【发布时间】:2022-01-22 10:22:24
【问题描述】:

我正在使用Reactive Form 创建一个项目;基于Recursive 组件从JSON 文件创建Dynamic Form

来源

这是 Ionic 基于Creating Dynamic Angular Forms with JSON 的改编

我改编了递归版本程序和其他更改!

我的代码位于Stackblitz

我将展示 json-form.component.html 文件的简化代码版本:

<form [formGroup]="myForm" (ngSubmit)="onSubmit()">
  <div fxLayout="column">
    <ng-container *ngFor="let control of jsonFormData?.controls">
      <div fxFlex="100%">
      
        <selects
          *ngIf="control.type === 'select'"
          [control]="control"
          [visible]="true"
        ></selects>
        
      </div>
    </ng-container>
  </div>
  <button mat-raised-button class="mt-1" color="primary">
    <em class="fa fa-save">Submit</em>
  </button>
</form>

如您所见,自定义组件是 selects

现在,让我们看一下 selects 模板的Recursive 使用代码。我再次减少了 select.component.html 文件的代码:

<form [formGroup]="form">
  <ng-container *ngIf="control?.children">
    <mat-form-field
      *ngIf="control.type === 'select' && control.visible"
      fxFlex="100%"
      hideRequiredMarker
    >
      <mat-label>{{ control.label }}</mat-label>
      <mat-select
        [formControlName]="control.name"
        [placeholder]="control.label"
        (selectionChange)="onSelectChange($event.value)"
      >
        <mat-option
          *ngFor="let child of control.children"
          [value]="child.value"
        >
          {{ child.label }}
        </mat-option>
      </mat-select>
    </mat-form-field>
  </ng-container>

  <ng-container *ngFor="let child of control?.children">
    <div fxFlex="100%">
      <selects *ngIf="child.type === 'select'" [control]="child"></selects>
    </div>
  </ng-container>
  
</form>

使用selects组件的递归代码为:

  <ng-container *ngFor="let child of control?.children">
    <div fxFlex="100%">
      <selects *ngIf="child.type === 'select'" [control]="child"></selects>
    </div>
  </ng-container>

错误示例如下:

ERROR
Error: Cannot find control with name: 'Petitioner (C2 -> P2)'

很遗憾,我找不到问题来解决它。

一些线索可以解决错误?

EDIT 我怀疑并非所有组件都会立即显示,只有在单击 Select 时才会显示;那么组件还没有被创建。

【问题讨论】:

  • 首先,您需要了解根 FormGroup 值的形状,然后使用嵌套控件生成该 FormGroup。我不明白最嵌套的配置:你为什么使用siblings 而不是children 并且它没有name 属性
  • @yurzui siblings 没有嵌套选择组件。对于这个例子可以忽略。抱歉,我没听懂首先,您需要了解根 FormGroup 值的形状。我试图理解,我正在尝试使用FormGroupDirective 指令关联SelectComponentFormGroup
  • 您只创建了顶级 FormGroup 并始终引用该根 FormGroup。
  • @yurzui 非常感谢您的宝贵时间。现在,我需要知道如何解决它!。
  • 这里是另一个例子dev.to/julianobrasil/…

标签: angular angular-material angular-reactive-forms recursive-component angular-dynamic-forms


【解决方案1】:

正如您在显示的视图中看到的那样,所有FormControl 都在那里。 但是,当出现点击事件时。我将我的Form 中的所有FormControl 显示在该行中:console.log(this.form.value);

正如您在Green 右下角矩形中看到的那样。 在上一个事件中。只出现了两个控件!!!,但是显示了7个没有按钮的formControls!... 那么我的Form(变量this.form)需要添加那些FormControl。

怎么做?

首先,我需要获得主要的FormFormGroup(我的父组件)。

json-form.component.ts 文件中的我的父组件 (JsonFormComponent) 中:

export class JsonFormComponent implements OnChanges {
  @Input() jsonFormData: JsonFormData;

  public myForm: FormGroup = this.fb.group({});
  public myFormBuilder: FormBuilder;

  constructor(private fb: FormBuilder) {
    this.myFormBuilder = fb;
  }

现在,我的父组件有public myForm: FormGroup...public myFormBuilder: FormBuilder;

下一步,在 selects.component.ts 文件中的每个子组件中创建局部变量。

export class SelectsComponent implements OnInit {
  public form: FormGroup;
  @Input() formBuilder: FormBuilder;

  constructor(private rootFormGroup: FormGroupDirective) {}

  ngOnInit(): void {
    this.form = this.rootFormGroup.form;
  }

现在,我有 public form: FormGroup...@Input() formBuilder: FormBuilder; 用于我的子组件!

下一步是将这些对象传递给我的子组件:

为了传递(或关联)myForm (FormGroup) 的解决方案来自这个post。 但是,myFormBuilder 的关系是在 json-form.component.html 文件中完成的。

    <selects
      *ngIf="control.type === 'select'"
      [control]="control"
      [visible]="true"
      (addControl)="onAddControl($event)"
      [formBuilder]="myFormBuilder"
    ></selects>

具体在一行:[formBuilder]="myFormBuilder"

对于递归,在 selects.component.html 文件中

  <ng-container *ngFor="let child of control?.children">
    <div fxFlex="100%">
      <selects
        *ngIf="child.type === 'select'"
        [control]="child"
        [formBuilder]="formBuilder"
      ></selects>
    </div>
  </ng-container>

具体在这一行:[formBuilder]="formBuilder"

现在,在 selects.component.ts 文件中的子组件中,我创建了这个方法:

  private newControl(control: JsonFormControls) {
    this.form.addControl(
      control.name,
      this.formBuilder.control(control.value, getValidators(control))
    );
    control.visible = true;
  }

最后:我改变了我的方法,为了添加需要显示的FormControl

  public onSelectChange(event: MatSelectChange) {
    console.log(this.form.value);
    this.control.value = event + '';
    if (this.control.children) {
      this.recursiveConcealer(this.control.children);
      const child = this.control.children.find(
        (child) => child.value === event + ''
      );
      this.newControl(child);
      if (child.siblings) {
        for (let sibling of child.siblings) {
          this.newControl(sibling);
        }
      }
    }
  }

请特别注意以下几行:this.newControl(child);this.newControl(sibling);

正如您在Blue 矩形中看到的,错误消失了。

注意:解决方案不止一个,这里有一个关于这个主题的questionHow can I pass the FormGroup of a parent component to its child component using the current Form API

【讨论】:

    猜你喜欢
    • 2021-08-15
    • 1970-01-01
    • 2019-08-20
    • 2020-01-28
    • 2019-01-24
    • 2019-10-13
    • 2018-03-23
    • 2018-07-22
    • 2020-03-30
    相关资源
    最近更新 更多