删除对被动表单的控制后,选择不更新UI的框

时间:2017-09-06 09:05:25

标签: angular typescript

我在这里使用"@angular/cli": "1.2.6""@angular/core": "^4.0.0"

我想做什么
我试图通过功能输入制作产品的反应形式。在表单内部,如果用户单击"添加功能"按钮,一个新的功能列,包括一个选择框" type"会出现。一旦用户点击"删除"在要素列内的按钮,该要素列将被删除。

我遇到了什么问题
问题是当我尝试删除第一个和最后一个功能列之间的功能列时,formControl已成功更新为正确的值。但是,已删除功能列的选择框的UI将传递到即将发布的下一个功能列。

我期望拥有什么
删除目标要素列后,即将发布的要素列的用户界面将显示正确的值。

示例
1.我尝试删除第二个功能列。 enter image description here 2. formControl成功删除了第二个功能。 UI中的第二个功能列已成功删除。但是,第三个要素列会上升,并使用已删除要素的选择框值替换该空格。 enter image description here

我的代码如下:

产品form.component.ts

formDOM;
features = [];
featureTypes = [
  { id: "pros", name: "pros" },
  { id: "cons", name: "cons" }];

ngOnInit() {
  this.formDOM = this.formBuilder.group({
    // Have other field....
    feature: this.formBuilder.array([])
  });
}

patchSingleFeature(feature: object): FormGroup {
  let returnObject = this.formBuilder.group({
    type: (feature && feature['type'])
    // some other field also....
  });

  this.features.push("feature");
  return returnObject;
}

addFeature(): void {
  let featureControl = <FormArray>this.formDOM.controls['feature'];
  featureControl.push(this.patchSingleFeature(new Feature()));
}

removeFeature(x: number): void {
  let numberOfFeature = this.features.length;
  let featureControl = <FormArray>this.formDOM.controls['feature'];
  featureControl.controls.splice(x, 1);
  this.features.splice(x, 1);
}

产品form.component.html

<div class="form" [formGroup]="formDOM">
  <div class="col-xs-12">Features</div>
  <div *ngFor="let feature of features; let x = index; ">
    <feature-input [x]="x" [featureTypes]="featureTypes" [form]="formDOM" (clickEvent)="removeFeature($event)"></feature-input>
  </div>
  <button (click)="addFeature()">Add Feature</button>
</div>

feature-input.component.html

<div class="feature-input" [formGroup]="form">
  <div formArrayName="feature">
    <div [formGroupName]="x">
      <select formControlName="type">
        <option value="" disabled>-- Select Feature Type --</option>
        <option *ngFor="let type of featureTypes" [value]="type.id">{{ type.name }}</option>
      </select>
    </div>
  </div>
</div>

特征input.component.ts

@Input() form: FormGroup;
@Input() featureTypes: Array<object>;
@Input() x: number;
@Output() clickEvent new EventEmitter<number>();

removeFeature(x) { this.clickEvent.emit(x); }

2 个答案:

答案 0 :(得分:1)

我会对您的代码进行一些更改。我会将整个formarray发送到子组件并在那里迭代它。由于JS中的对象是可变的,因此您不需要EventEmitter,但您可以在子节点中执行删除操作,而不向父节点发送任何内容。

因此,在这种情况下,由于您没有嵌套表单组,请将整个表单传递给子表单:

<feature-input [featureTypes]="featureTypes" [formGroup]="formDOM"></feature-input>

对输入字段进行适当的更改,然后您的子模板将如下所示:

<div [formGroup]="formGroup">
  <div class="feature-input" formArrayName="feature">
    <div *ngFor="let ctrl of formGroup.controls.feature.controls; let i = index" [formGroupName]="i">
      <select formControlName="type">
      <option value="" disabled>-- Select Feature Type --</option>
      <option *ngFor="let type of featureTypes" [value]="type.id">{{ type.name }}</option>
      </select>
      <button (click)="removeFeature(i)">Remove</button>    
    </div>
  </div>
</div>

removeFeature中,我们只传递表单组的索引并使用函数removeAt,该函数可用于表单数组:

removeFeature(index) {
  this.formGroup.controls.feature.removeAt(index)
}

就是这样!这是一个演示:https://plnkr.co/edit/kZComoNNfsbCjmVnGt1F?p=preview

答案 1 :(得分:0)

您应该直接在 FormArray 上使用带有索引的 removeAt。

(<FormArray>this.myForm.controls['items']).removeAt(index);

如果您在表单控件上使用 splice,那么您必须对每个项目使用 updateValueAndValidity,然后它将更新数组。

this.formControls.splice(index, 1)

this.formControls.map(data => {data[controls].value.updateValueAndValidity({ onlySelf: false, emitEvent: false });});