带有嵌套组的 Angular 4 动态表单 [英] Angular 4 Dynamic form with nested groups

查看:18
本文介绍了带有嵌套组的 Angular 4 动态表单的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想从树结构中生成一个反应形式.

这是创建表单项(表单组和控件)的代码.对于嵌套在表单组中的控件,我使用递归模板.

import { Component, Input, NgModule } from '@angular/core';从'@angular/platform-b​​rowser' 导入 { BrowserModule };import { FormBuilder, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms';@成分({选择器:'表单项',模板:`<ng-container [formGroup]="form"><ng-container *ngTemplateOutlet="formItemTemplate; context:{ $implicit: pathSegments }"></ng-container><ng-template #formItemTemplate let-pathSegments><ng-container *ngIf="pathSegments.length > 1"><div [formGroupName]="pathSegments[0]" class="form-group"><ng-container *ngTemplateOutlet="formItemTemplate; context:{ $implicit: pathSegments.slice(1) }"></ng-container>

</ng-容器><ng-container *ngIf="pathSegments.length === 1"><div class="form-control"><label>{{pathSegments[pathSegments.length - 1]}}</label><!--<input type="text" [formControlName]="pathSegments[pathSegments.length - 1]"/>--><input type="text"/>

</ng-容器></ng-模板></ng-容器>`,})导出类 AppControlComponent {@Input() 表单:FormGroup;@输入()设置路径(路径:字符串){this.pathSegments = path.split('.');}路径段:字符串[] = [];构造函数(){}}@成分({选择器:'app-root',模板:`<form [formGroup]="questionForm"><h1>问题表</h1><form-item [form]="questionForm" path="question"></form-item><form-item [form]="questionForm" path="answers.answer1"></form-item><form-item [form]="questionForm" path="answers.answer2"></form-item><form-item [form]="questionForm" path="answers.answer3"></form-item><button type="submit">submit</button><pre>{{questionForm.value |json}}</pre></表单>`,})导出类 AppComponent {私人问题表格:FormGroup;构造函数(私人FB:FormBuilder){this.questionForm = this.fb.group({问题:['', Validators.required],答案:this.fb.group({答案 1: ['', Validators.required],答案 2: ['', Validators.required],答案 3: ['', Validators.required],}),});}}@NgModule({进口:[BrowserModule,FormsModule,ReactiveFormsModule],声明: [应用组件,应用控制组件],引导程序:[AppComponent]})导出类 AppModule {}

表单 HTML 完美生成.但是当我将 formControlName 指令添加到输入时,HTML 生成会中断.然后我得到这样的错误:

错误:找不到名称为answer1"的控件

解决方案

为了支持无限数量的嵌套组,我会使用如下标记:

<ng-容器*ngTemplateOutlet="formItemTemplate; context:{ $implicit: 0, group: form }"></ng-容器><ng-template #formItemTemplate let-i let-group="group"><fieldset *ngIf="i < pathSegments.length - 1" class="form-group"><legend>{{ pathSegments[i] }}</legend><ng-容器*ngTemplateOutlet="formItemTemplate;上下文:{ $implicit: i + 1, group: group.get(pathSegments[i]) }"></ng-容器></fieldset><div *ngIf="i + 1 === pathSegments.length" class="form-control" [formGroup]="group"><label>{{pathSegments[pathSegments.length - 1]}}</label><input [formControlName]="pathSegments[pathSegments.length - 1]"/>

</ng-模板></ng-容器>

Plunker 示例

I want to generate a reactive form from the tree structure.

Here is the code that creates the form items (form groups and controls). For the controls nested in form group it I use a recursive template.

import { Component, Input, NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormBuilder, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms';

@Component({
  selector: 'form-item',
  template: `
    <ng-container [formGroup]="form">
      <ng-container *ngTemplateOutlet="formItemTemplate; context:{ $implicit: pathSegments }"></ng-container>

      <ng-template #formItemTemplate let-pathSegments>
        
        <ng-container *ngIf="pathSegments.length > 1">
          <div [formGroupName]="pathSegments[0]" class="form-group">
            <ng-container *ngTemplateOutlet="formItemTemplate; context:{ $implicit: pathSegments.slice(1) }"></ng-container>
          </div>
        </ng-container>

        <ng-container *ngIf="pathSegments.length === 1">
          <div class="form-control">
            <label>{{pathSegments[pathSegments.length - 1]}}</label>
            <!--<input type="text" [formControlName]="pathSegments[pathSegments.length - 1]"/>-->
            <input type="text"/>
          </div>
        </ng-container>
        
      </ng-template>
    </ng-container>
  `,
})
export class AppControlComponent {

  @Input() form: FormGroup;

  @Input()
  set path(path: string) {
    this.pathSegments = path.split('.');
  }
  pathSegments: string[] = [];

  constructor() { }
}


@Component({
  selector: 'app-root',
  template: `
    <form [formGroup]="questionForm">
      <h1>Question Form</h1>

      <form-item [form]="questionForm" path="question"></form-item>
      <form-item [form]="questionForm" path="answers.answer1"></form-item>
      <form-item [form]="questionForm" path="answers.answer2"></form-item>
      <form-item [form]="questionForm" path="answers.answer3"></form-item>

      <button type="submit">submit</button>

      <pre>{{questionForm.value | json}}</pre>
    </form>
  `,
})
export class AppComponent {
  private questionForm: FormGroup;

  constructor(private fb: FormBuilder) {
    this.questionForm = this.fb.group({
      question: ['', Validators.required],
      answers: this.fb.group({
        answer1: ['', Validators.required],
        answer2: ['', Validators.required],
        answer3: ['', Validators.required],
      }),
    });
  }
}

@NgModule({
  imports: [BrowserModule, FormsModule, ReactiveFormsModule],
  declarations: [
    AppComponent,
    AppControlComponent
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}

The form HTML is generated perfectly. But when I add the formControlName directive to the input the HTML generation breaks. Then I get such error:

Error: Cannot find control with name: 'answer1'

解决方案

To support unlimited number of nested group i would use markup like:

<ng-container [formGroup]="form">
  <ng-container 
     *ngTemplateOutlet="formItemTemplate; context:{ $implicit: 0, group: form }">
  </ng-container>

  <ng-template #formItemTemplate let-i let-group="group">
      <fieldset *ngIf="i < pathSegments.length - 1" class="form-group">
        <legend>{{ pathSegments[i] }}</legend>
        <ng-container 
          *ngTemplateOutlet="formItemTemplate; 
          context:{ $implicit: i + 1, group: group.get(pathSegments[i]) }">
        </ng-container>
      </fieldset>

      <div *ngIf="i + 1 === pathSegments.length" class="form-control" [formGroup]="group">
        <label>{{pathSegments[pathSegments.length - 1]}}</label>
        <input [formControlName]="pathSegments[pathSegments.length - 1]"/>
      </div>
  </ng-template>
</ng-container>

Plunker Example

这篇关于带有嵌套组的 Angular 4 动态表单的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆