Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/29.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
带formarray的angular中的动态表单生成器_Angular_Angular11 - Fatal编程技术网

带formarray的angular中的动态表单生成器

带formarray的angular中的动态表单生成器,angular,angular11,Angular,Angular11,我已经在我的项目中实现了动态表单生成器,它运行良好。但是,现在我需要在动态表单生成器中添加一个表单。这就像是表单中的表单。所以,我已经在我的ts中创建了一个formarray,它正在正确地进行 我得到了一个错误,就像 错误:找不到名为“891713”的控件。 这就是我所实现的 我使用的代码示例是 因此,我在“atoms”文件夹中创建了一个名为formControl的组件,如果该控件是fromControl,我将再次调用field control 表单控制组件 <t

我已经在我的项目中实现了动态表单生成器,它运行良好。但是,现在我需要在动态表单生成器中添加一个表单。这就像是表单中的表单。所以,我已经在我的ts中创建了一个formarray,它正在正确地进行

我得到了一个错误,就像

错误:找不到名为“891713”的控件。

这就是我所实现的

我使用的代码示例是

因此,我在“atoms”文件夹中创建了一个名为formControl的组件,如果该控件是fromControl,我将再次调用field control

表单控制组件

            <td *ngFor="let itm of items; let i = index" formArrayName="childs" >
              <field-builder [field]="itm" [form]="form" ></field-builder>
            </td>
有人能帮我解决这个问题吗?
提前感谢!:)

puff,这是一个庞大而复杂的改进代码,以允许fromGroups和formArray,但我们将尝试一下

首先,我们将对DynamicFormBuilderComponent进行一些更改

我们将创建一个函数getForm,使其能够递归地创建formGroup

  getForm(group: FormGroup, fields: any[]) {
    for (let f of fields) {
      switch (f.type) {
        case "group":
          group.addControl(f.name, new FormGroup({}));
          this.getForm(group.get(f.name) as FormGroup, f.children);

          break;
        case "checkbox":
          group.addControl(f.name, new FormGroup({}));
          const groupOption = group.get(f.name) as FormGroup;
          for (let opt of f.options) {
            groupOption.addControl(opt.key, new FormControl(opt.value));
          }
          break;
        case "array":
          group.addControl(f.name, new FormArray([]));
          const array = group.get(f.name) as FormArray;
          if (f.value)
          {
              f.value.forEach(x=>array.push(this.addGroupArray(f.children)))
              array.patchValue(f.value)
          }

        break;
        default:
          group.addControl(
            f.name,
            new FormControl(f.value || "", Validators.required)
          );
          break;
      }
    }
在创建对象
fields
并最终将对象字段添加到formGroup之前,请先了解这一点。使用此函数,我们直接创建一个空formGroup,并使用
group.addControl
添加FormControls或formGroup或FormArray。这允许我们在必要时调用递归函数

所以,在恩戈尼尼特我们制造

  ngOnInit() {
    this.getForm(this.form, this.fields);
  }
请注意,我们可以使用模板变量从父级访问表单

<dynamic-form-builder #dynamic ..>
{{dynamic.form?.value|json}}
我们的FieldBuilder组件应该考虑新的两种类型的字段:“数组”和“组”。我要把它放在一个野外装置里

  <!--in case group we repeat the field-builder using
     as form the "getFormGroup" and as field "field.children"
  -->
  <fieldset *ngSwitchCase="'group'">
     <legend>{{field.name}}</legend>
     <field-builder *ngFor="let item of field.children"
       [form]="getFormGroup(field.name)" [field]="item">
     </field-builder>
  </fieldset>

  <!--in case array we create a table and use the function
      "getFormArray"
  -->

  <fieldset *ngSwitchCase="'array'">
     <legend>{{field.name}}</legend>
      <table [formArrayName]="field.name">
        <tr>
          <th *ngFor="let item of field.children">{{item.label}}</th>
          <th>
          <button class="btn btn-primary" (click)="getFormArray(field.name).push(this.addGroupArray(field.children))">Add</button>
          </th>
        </tr>
        <tr *ngFor="let group of getFormArray(field.name).controls;let i=index" [formGroupName]="i">
           <td *ngFor="let item of field.children">
              <field-builder noLabel="true" [form]="getFormArray(field.name).at(i)"
                [field]="item">
              </field-builder>
            </td>
            <td><button class="btn btn-primary" (click)="getFormArray(field.name).removeAt(i)">Delete</button></td>
        </tr>
      </table>
    </fieldset>
看看我们如何在内部调用自己的组件。我需要添加一个“属性”noLabel,以便在我们使用FormArrayLabel时不显示标签

  //in constructor
  constructor(@Attribute('noLabel') noLabel) { 
    this.noLabel=noLabel || false;
  }
和使用

 <label *ngIf="!noLabel" ....></label>
通常这是没有保证的

注意:选项的原子应该是

  <div [formGroup]="form">
    <div class="form-check" *ngFor="let opt of field.options">
      <label class="form-check-label">
      <input [formControlName]="field.name"  class="form-check-input" type="radio" [value]="opt.key" >
        {{opt.label}}
      </label>
    </div>
  </div> 
现在我们可以使用[ngModel]和(ngModelChange)。我们需要说这是一个“独立的”


puff,这是一个巨大而复杂的改进代码,以允许fromGroups和formArray,但我们将尝试

首先,我们将对DynamicFormBuilderComponent进行一些更改

我们将创建一个函数getForm,使其能够递归地创建formGroup

  getForm(group: FormGroup, fields: any[]) {
    for (let f of fields) {
      switch (f.type) {
        case "group":
          group.addControl(f.name, new FormGroup({}));
          this.getForm(group.get(f.name) as FormGroup, f.children);

          break;
        case "checkbox":
          group.addControl(f.name, new FormGroup({}));
          const groupOption = group.get(f.name) as FormGroup;
          for (let opt of f.options) {
            groupOption.addControl(opt.key, new FormControl(opt.value));
          }
          break;
        case "array":
          group.addControl(f.name, new FormArray([]));
          const array = group.get(f.name) as FormArray;
          if (f.value)
          {
              f.value.forEach(x=>array.push(this.addGroupArray(f.children)))
              array.patchValue(f.value)
          }

        break;
        default:
          group.addControl(
            f.name,
            new FormControl(f.value || "", Validators.required)
          );
          break;
      }
    }
在创建对象
fields
并最终将对象字段添加到formGroup之前,请先了解这一点。使用此函数,我们直接创建一个空formGroup,并使用
group.addControl
添加FormControls或formGroup或FormArray。这允许我们在必要时调用递归函数

所以,在恩戈尼尼特我们制造

  ngOnInit() {
    this.getForm(this.form, this.fields);
  }
请注意,我们可以使用模板变量从父级访问表单

<dynamic-form-builder #dynamic ..>
{{dynamic.form?.value|json}}
我们的FieldBuilder组件应该考虑新的两种类型的字段:“数组”和“组”。我要把它放在一个野外装置里

  <!--in case group we repeat the field-builder using
     as form the "getFormGroup" and as field "field.children"
  -->
  <fieldset *ngSwitchCase="'group'">
     <legend>{{field.name}}</legend>
     <field-builder *ngFor="let item of field.children"
       [form]="getFormGroup(field.name)" [field]="item">
     </field-builder>
  </fieldset>

  <!--in case array we create a table and use the function
      "getFormArray"
  -->

  <fieldset *ngSwitchCase="'array'">
     <legend>{{field.name}}</legend>
      <table [formArrayName]="field.name">
        <tr>
          <th *ngFor="let item of field.children">{{item.label}}</th>
          <th>
          <button class="btn btn-primary" (click)="getFormArray(field.name).push(this.addGroupArray(field.children))">Add</button>
          </th>
        </tr>
        <tr *ngFor="let group of getFormArray(field.name).controls;let i=index" [formGroupName]="i">
           <td *ngFor="let item of field.children">
              <field-builder noLabel="true" [form]="getFormArray(field.name).at(i)"
                [field]="item">
              </field-builder>
            </td>
            <td><button class="btn btn-primary" (click)="getFormArray(field.name).removeAt(i)">Delete</button></td>
        </tr>
      </table>
    </fieldset>
看看我们如何在内部调用自己的组件。我需要添加一个“属性”noLabel,以便在我们使用FormArrayLabel时不显示标签

  //in constructor
  constructor(@Attribute('noLabel') noLabel) { 
    this.noLabel=noLabel || false;
  }
和使用

 <label *ngIf="!noLabel" ....></label>
通常这是没有保证的

注意:选项的原子应该是

  <div [formGroup]="form">
    <div class="form-check" *ngFor="let opt of field.options">
      <label class="form-check-label">
      <input [formControlName]="field.name"  class="form-check-input" type="radio" [value]="opt.key" >
        {{opt.label}}
      </label>
    </div>
  </div> 
现在我们可以使用[ngModel]和(ngModelChange)。我们需要说这是一个“独立的”


请在此处为表单和字段生成器共享相应的TS代码。那么您是在同一组件中递归调用“字段控制”?这其中的逻辑在哪里?你为什么这么做?@willialexander我也添加了TS代码。所有其他代码在stackblitz链接中都是相同的mentioned@VimalPatel这实际上是我的要求。请在这里为表单和字段生成器共享适当的TS代码。那么您是在同一组件中递归调用“字段控制”?这其中的逻辑在哪里?你为什么这么做?@willialexander我也添加了TS代码。所有其他代码在stackblitz链接中都是相同的mentioned@VimalPatel这实际上是我的要求。非常感谢@Eliseo。我可以通过调查你在这里的方式来解决我的问题,非常感谢@Eliseo。我可以通过调查你在这里的表现来解决我的问题
  getForm(group: FormGroup, fields: any[]) {
    for (let f of fields) {
      switch (f.type) {
        case "group":
          ...
          break;
        case "array":
           ....
        break;
        default:
          ...
          break;
      }
    }
  }