Angular 表单:如何动态添加/删除子表单组件

Posted

技术标签:

【中文标题】Angular 表单:如何动态添加/删除子表单组件【英文标题】:Angular form: How to dynamically add/remove subform Component 【发布时间】:2020-09-09 00:07:05 【问题描述】:

我希望在主窗体中能够动态添加/删除子窗体。 子表单基于模型对象,并嵌入了一些东西:

使用从父表单组件传输的数据(用于选择输入选项) 具有事件触发onChange功能 可以在编辑模式下使用,这样可以允许表单预填

然后我为这个子表单创建一个专用组件:

型号:

impoort  Obj  from ./Obj.model.ts
export class Foo
 
  constructor(
  public name: string,
  public obj: Obj,
    public bar: string
  ) 

subform.component.ts:


@Component(
  selector: 'ngx-subformcomp',
  templateUrl: './subform.component.html',
  styleUrls: ['./subform.component.scss']
)
export class SubformComponent implements OnInit, OnDestroy 

  @Input() objs: Obj[];
  @Input() foodata?: Foo;

  subForm: FormGroup;
  showBar: boolean = true;

  constructor(
    private formBuilder: FormBuilder,
    private loadingService: LoadingService,
  )  

  ngOnInit(): void 
    initForm();
    if (foodata) 
      //In case Edit mode
      this.subForm.patchValue(
        name: foodata.name,
        obj: foodata.obj,
        bar: foodata.bar,
      );
      if (foodata.obj.id == 1) 
        this.subForm.get('bar').setValidators([Validators.required]);
        this.subForm.get('bar').updateValueAndValidity();
        this.showbar = true;
      
      else 
        this.subForm.patchValue( bar: '' );
        this.subForm.get('bar').setValidators([]);
        this.subForm.get('bar').updateValueAndValidity();
      
    
  

  initForm() 
    this.subForm = this.formBuilder.group(
      name: ['', [Validators.required],
        obj: new FormControl('', [Validators.required, SelectedValue]),
        bar: ['', [Validators.required],
          ,
      
        validator: [... , ...]
      );
  

  onObjChange(event) 
    if (event == 1) 
      this.subForm.get('bar').setValidators([Validators.required]);
      this.subForm.get('bar').updateValueAndValidity();
      this.showbar = true;
    
    else 
      this.subForm.patchValue( bar: '' );
      this.subForm.get('bar').setValidators([]);
      this.subForm.get('bar').updateValueAndValidity();
    

  

html

<form [formGroup]="subForm">    
    <div class="form-group">
      <input id="name" class="form-control" formControlName="name" />   
    </div>
    <div class="form-group">
      <nb-select id="obj" formControlName="obj" (selectedChange)="onObjChange($event)">
        <nb-option *ngFor="let option of objs" [value]="option.id"> option.label </nb-option>
      </nb-select>
    </div>
    <div class="form-group">
      <input *ngIf="showBar" id="bar" class="form-control" formControlName="bar" />   
    </div>
 </form>

我现在尝试在我的主要表单中使用它,但我迷路了......

我这样定义了我的主要表单组件:

export class MainComponent implements OnInit, OnDestroy 
  objs:Obj[] = [....],
  mainForm: FormGroup;

 ngOnInit(): void 
  initForm();
    

 initForm() 
    this.mainForm = this.formBuilder.group(
      foobar: ['', [Validators.required],
  objs: this.formBuilder.array([]),
    , 
    
      validator: [... ,...]
    ); 

 

getObjs(): FormArray 
  return this.sMainForm.get('objs') as FormArray;


onAddObj() 

在我的模板中:

<div class="form-group">
    <ng-container formArrayName="objs" *ngFor="let obj of objs; let i=index">
        <ngx-subformcomp id="'gsprice_'+i" [formControlName]="objs[i]"></ngx-subformcomp>
    </ng-container>
    <button (click)="onAddObj()" outline>Add</button>
</div>

我不知道如何对待 onAddObj 函数和即将到来的 removeObj... 谢谢你的帮助

【问题讨论】:

【参考方案1】:

我在这里看到很多混乱(:

首先,这不是您可以迭代FormArray 的方式。正确的方法是

<div *ngFor="let ctr of objs.controls;">

这样ctr 将包含FormGroup。 下一个,ngx-subformcomp[formControlName]='obj'[formControl]='obj'提供的表单控件通信,需要implement control value accessor interface。一开始可能会很棘手。为了向前迈出更小的一步,您可能希望将ctr 权限传递给ngx-subformcomp

还有最大的一个? 乍一看,在控件之间分离管理表单部分的职责似乎总是一个好主意。就像一个组件管理数组一样,另一个组件管理项目。在实践中它变得痛苦。很快,逻辑就在几个组件中传播开来。很难理解表单控件之间的所有验证和依赖关系。根据我的经验,对于复杂的表单,管理一个包含所有验证、所有依赖项、所有结构和特定于该表单的助手的服务总是很容易。这样的服务也很容易被单元测试覆盖。组件仅用于显示数据并将用户输入绑定到 HTML 控件,仅此而已。使用这种方法可以更轻松地维护代码?

【讨论】:

以上是关于Angular 表单:如何动态添加/删除子表单组件的主要内容,如果未能解决你的问题,请参考以下文章

angular 7 反应式表单:为表单中的每个输入字段动态添加/删除输入字段

Angular2动态添加/删除表单字段

如何从 Angular 6 中的父组件访问子组件中的表单?

如何删除 Angular 表单组中的特定错误

Angular 2 动态嵌套表单

如何将表单组绑定到 Angular 中嵌套的动态创建的组件