动态角度形式清除现有值

时间:2018-01-18 20:53:45

标签: angular forms dynamic

StackBlitzExample

我正在尝试为地址集合创建一个简单的组件。用户可以添加,删除和编辑所有地址。除了存在多个地址外,用户只删除第一个地址,然后添加新地址。添加了新地址,但也清除了现有地址。在我的应用程序中,我也得到错误 - ExpressionChangedAfterItHasBeenCheckedError。



import { Component, Input } from '@angular/core';

@Component({
  selector: 'hello',
  template: `<h1>Hello {{name}}!</h1><button type="button" (click)="add()">Add</button>
  <form>
  <div *ngFor="let addr of data; let i=index;">
    <input  name="{{'address1'+i}}" type="text" [(ngModel)]="addr.address1" />
    <input  name="{{'zip'+i}}" type="text" [(ngModel)]="addr.zip" />
    <button type="button" (click)="delete(i, addr)">Delete</button>
    <hr/>
  </div>
  </form>
  `,
  styles: [`h1 { font-family: Lato; }`]
})
export class HelloComponent  {
  @Input() name: string;
  data = [
    {
      address1:'500 Main St',
      address2:'',
      city:'Norman',
      state:'OK',
      zip:'73070'
    },
    {
      address1:'501 Main St',
      address2:'',
      city:'OKC',
      state:'OK',
      zip:'73105'
    }
  ];


  add() {
    this.data.push( { address1:'',
      address2:'',
      city:'',
      state:'',
      zip:''});
  }

  delete(index:number, row:any) {
   this.data.splice(index, 1);
  }
}
&#13;
&#13;
&#13;

2 个答案:

答案 0 :(得分:2)

我能够通过使用ngFor的trackBy功能来完成工作。这是修改后的代码,也对StackBlitz进行了修正。

    @Component({
  selector: 'hello',
  template: `<h1>Hello {{name}}!</h1><button type="button" (click)="add()">Add</button>
  <form>
  <div *ngFor="let addr of data; let i=index; trackBy:trackByIndex">
    <input  name="{{'address1'+i}}" type="text" [(ngModel)]="addr.address1" />
      <input  name="{{'address2'+i}}" type="text" [(ngModel)]="addr.address2" />
        <input  name="{{'city'+i}}" type="text" [(ngModel)]="addr.city" />
          <input  name="{{'state'+i}}" type="text" [(ngModel)]="addr.state" />
            <input  name="{{'zip'+i}}" type="text" [(ngModel)]="addr.zip" />
            <button type="button" (click)="delete(i, addr)">Delete</button>
            <hr/>
  </div>
  </form>
  `,
  styles: [`h1 { font-family: Lato; }`]
})
export class HelloComponent  {
  @Input() name: string;
  data = [
    {
      address1:'500 Main St',
      address2:'',
      city:'Norman',
      state:'OK',
      zip:'73070'
    },
    {
      address1:'501 Main St',
      address2:'',
      city:'OKC',
      state:'OK',
      zip:'73105'
    }
  ];


  add() {
    this.data.push( { address1:'',
      address2:'',
      city:'',
      state:'',
      zip:''});
  }

  public trackByIndex(index: number, value: number) {
    return index;
  }

  delete(index:number, row:any) {
   this.data.splice(index, 1);
  }
}

答案 1 :(得分:0)

你想要一个FormArray。它非常适合这种事情。我已经继续使用Reactive Forms重新创建您的应用程序,因此您可以比较和对比,看看它是如何工作的。

以下是包含所有代码的工作示例的链接:https://stackblitz.com/edit/angular-eeamqq

请注意,我将反应形式的值添加到模板中,因此您可以看到它本质上是一个动态构建的对象。

如果您希望我进一步扩展我在上述应用中使用的一些技术,请告诉我。

我还会在这里链接代码,以便您可以在不加载应用程序的情况下查看它:

模板:

  <button type="button" (click)="onAdd()">Add</button>
  <hr>

  <form [formGroup]="addressForm">
    <div formArrayName="addresses" 
         *ngFor="let address of addressForm.get('addresses').controls; let i = index;">
      <div [formGroupName]="i">
         <input formControlName="address1" placeholder="Address 1">
         <input formControlName="address2" placeholder="Address 2">
         <input formControlName="city" placeholder="City">
         <input formControlName="state" placeholder="State">
         <input formControlName="zip" placeholder="Zip">
         <button (click)="onDelete(i)">Delete</button>
      </div>
      <hr>
    </div>
  </form>

组件类的重要部分:

  constructor(private fb: FormBuilder) {}

  ngOnInit() {
    const addressForms = this.data.map(address => this.createAddressForm(address));

    this.addressForm = this.fb.group({
      addresses: this.fb.array(addressForms)
    });
  }

  createAddressGroup(address?: any) {
    return this.fb.group({
      address1: address ? address.address1 : '',
      address2: address ? address.address2 : '',
      city: address ? address.city : '',
      state: address ? address.state : '',
      zip: address ? address.zip : ''
    });
  }

  onAdd() {
    const addresses = this.addressForm.get('addresses') as FormArray;
    addresses.push(this.createAddressForm());
  }

  onDelete(index: number) {
    const addresses = this.addressForm.get('addresses') as FormArray;
    addresses.removeAt(index);
  }