【问题标题】:Generate form trough loop生成形式槽循环
【发布时间】:2021-05-06 14:45:10
【问题描述】:

我试图通过循环生成一个表单组,所以我有一些输入,并基于它创建一个带有嵌套组的表单。我的想法是这样的:

public transactionOrRefundRequestForm: FormGroup = new FormGroup({});

this.transactionOrRefundRequestForm.addControl('SaleToPos', new FormGroup(
      this.generateForm(this.formStructure)
    ));


 public generateForm(formEntry: FormEntry[] | null | undefined): any {

  formEntry.forEach(fe => {
    console.log(fe);
    console.log(this.transactionOrRefundRequestForm.controls);

    if (fe instanceof FormCategory) {
      const fc = fe as FormCategory;

     return {fc.name : new FormGroup(this.generateForm(fc.entries))};
    }

    if (fe instanceof FormInput || FormInputSelect || FormInputBoolean) {
      const fi = fe as FormInput;
 
      return {fi.name: new FormControl('')};
    }

  });

}

所以当我得到输入时,它会循环遍历它,如果是输入,它将返回新的 formControl,但如果是类别,它将返回新的 FormGroup,其子项将被函数再次循环。

现在我的结果是一个空表单,但我不确定我做错了什么。

这是一个堆栈闪电战:https://stackblitz.com/edit/angular-ivy-nqndkq?file=src/app/app.component.ts

它会为没有构造函数的类抛出错误,但对我来说它工作得很好。太糟糕了,我不知道该怎么办,抱歉。

【问题讨论】:

  • 你能在这里分享 stackblitz 链接吗?并在那里添加代码
  • 您的代码存在编译问题,并且您同时询问多个问题,请改进您的问题以获得更好的答案
  • @MauricioGraciaGutierrez 是的,它有编译问题,但它们没有意义,因为它要求一个构造函数,即使有一个也很困难。此外,我看不出我在哪里同时询问多个问题,但无论哪种方式,我都会尝试改进它。
  • 那个“构造函数错误”是因为在app.component.ts的第164行创建新的class FormEntry之前没有关闭上一个类,这是我建议你分开的原因之一每个类的文件。

标签: angular forms loops


【解决方案1】:

使用map 操作符代替forEach,如果我们在forEach 中返回任何内容,它不会返回任何内容,它只会返回未定义的内容。

public generateForm(formEntry: FormEntry[] | null | undefined): any {

  return formEntry.map(fe => {
    console.log(fe);
    console.log(this.transactionOrRefundRequestForm.controls);

    if (fe instanceof FormCategory) {
      const fc = fe as FormCategory;

     return {fc.name : new FormGroup(this.generateForm(fc.entries))};
    }

    if (fe instanceof FormInput || FormInputSelect || FormInputBoolean) {
      const fi = fe as FormInput;
 
      return {fi.name: new FormControl('')};
    }

  });
}

【讨论】:

  • fi.name : new FormControl,看起来“:”应该是“,”对吗?看看我下面的答案
  • 嗨 @MauricioGraciaGutierrez 我认为由于 fi.name 是动态值,它应该是这样的 [fi.name] : new FormControl
  • 好吧,我将您的代码复制粘贴到 stackblitz 中,但它有语法错误
  • 我尝试使用它,但它给了我一个 {}。 ://
  • 这是因为generateForm方法根据条件返回formGroup或FormControl的数组,generateForm应该返回对象
【解决方案2】:

这也部分包含问题Generate table from form的解决方案

所以我设法以递归方式生成它,就是这样,代码有点长,所以如果你迷路了回复我,我会尝试编辑它并更好地澄清它:

所以首先生成你的默认表单结构。

我的看起来像这样:

this.formStructure =
      new FormCategory(
        'SaleToPOIRequest',
        [
          new FormCategory(
            'AdminRequest',
            [
              new FormInput('ServiceIdentification', '', [Validators.required]),
            ])
        ]);

然后是逻辑:

生成默认表单后我this.reconstructForm();

 private reconstructForm(): void {
    const oldValue = this.rebootRequestForm.value;
    this.rebootRequestForm = new FormGroup({});
    this.generateFormBranch(this.rebootRequestForm, [this.formStructure]);
    this.rebootRequestForm.patchValue(oldValue);
  }

这将触发this.generateFormBranch()

public generateFormBranch(parent: FormGroup, structure: FormEntry[]) {
    structure.forEach(formEntry => {
      if (formEntry instanceof FormInput) {
        parent.addControl(this.toInput(formEntry).name,
          new FormControl(this.toInput(formEntry).defaultValue, this.toInput(formEntry).validation));
      }
      if (formEntry instanceof FormCategory) {
        const formGroup = new FormGroup({});
        this.generateFormBranch(formGroup, formEntry.entries);
        if (formEntry.parent) {
          parent.addControl(formEntry.name, formGroup);
        } else {
          this.rebootRequestForm.addControl(formEntry.name, formGroup);
        }
      }
    });
  }

这将为我生成表单,我可以像这样添加类别和输入:

public addCategory(parent: FormCategory): void {
    const dialogRef = this.dialog.open(FormUpdateDialogComponent, {
      data: <FormUpdateDialogComponent> {
        dialogType: 'category',
      }
    });
    dialogRef.afterClosed()
      .subscribe(data => {
        this.checkAndAddFormControl(parent, data, FormCategory);
      });
  }

  public addInput(parent: FormCategory): void {
    const dialogRef = this.dialog.open(FormUpdateDialogComponent, {
      data: <FormUpdateDialogComponent> {
        dialogType: 'input',
      }
    });
    dialogRef.afterClosed()
      .subscribe(data => {
        this.checkAndAddFormControl(parent, data, FormInput);
      });
  }

两者都会触发:this.checkAndAddFormControl()

checkAndAddFormControl(parent: FormCategory, name: string, type) {
    let isAvailable = true;
    parent.entries.forEach(entry =>
      entry.name === name ? isAvailable = false : isAvailable);

    if (type === FormInput) {
      if (isAvailable && name !== '') {
        parent.addEntry(new FormInput(name, '', []));
        this.reconstructForm();
        this.snackBar.open('Input ' + name + ' has been added at top of the category', 'OK');
      } else {
        this.snackBar.open('Name has already been set or it\'s null', 'OK');
      }
    }

    if (type === FormCategory) {
      if (isAvailable && name !== '') {
        parent.addEntry(new FormCategory(name, []));
        this.reconstructForm();
        this.snackBar.open('Category ' + name + ' has been added at the bottom of the category', 'OK');
      } else {
        this.snackBar.open('Name has already been set or it\'s null', 'OK');
      }
    }
  }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-29
    • 2018-08-26
    相关资源
    最近更新 更多