角形式:如何动态添加/删除子表单组件

问题描述 投票:1回答:1

我希望在Main窗体中能够动态添加/删除子窗体。子表单基于模型对象,并嵌入了几件事:

  • 使用从父表单组件传输的数据(用于选择输入选项)
  • 具有事件触发器的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() {
}

以及我的template

<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 ...谢谢您的帮助

angular dynamic nested-forms
1个回答
0
投票

我在这里看到很多困惑(:

首先,这不是您可以迭代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控件,仅此而已。使用这种方法可以更轻松地维护代码😊

© www.soinside.com 2019 - 2024. All rights reserved.