如何获取角形数组中已更改项的索引

时间:2017-07-13 17:18:35

标签: angular angular-reactive-forms formarray

我使用带反应形式的Angular 4。我有一个表单数组,我试图绑定到我在组件中跟踪的数组。我使用反应形式,所以我可以进行验证,所以我不想使用模板形式方法。

我将项添加到表单数组中,如下所示:

createFormWithModel() {
  this.orderForm = this.fb.group({
    orderNumber: [this.order.ProductBookingOrder],
    orderDate: [this.order.PurchaseOrderIssuedDate],
    lineDetailsArray: this.fb.array([])
  })

  const arrayControl = <FormArray>this.orderForm.controls['lineDetailsArray'];
  this.order.ProductBookingDetails.forEach(item => {
    let newGroup = this.fb.group({
      ProductName: [item.ProductName],
      Quantity: [item.ProductQuantity.Quantity],
      UOM: [item.ProductQuantity.UOM],
      RequestedShipDate: [item.RequestedShipDate]
    })
  })
}

orderForm显然是我的反应形式FormGroup。订单是我从API获取的对象,我想更新其值,包括行详细信息。我想我应该使用&#39; valueChanges.subscribe&#39;在每个newGroup上,但我不知道如何获取已更改的项目的索引。有什么想法吗?

     newGroup.valueChanges.subscribe('i want value and index some how' => {
this.order.ProductbookingDetails[index].ProductName = value.ProductName;
    });

以下是此部分的HTML:

<tbody formArrayName="lineDetailsArray">
        <tr [formGroupName]="i" *ngFor="let line of orderForm.controls['lineDetailsArray'].controls; index as i">
          <td><input class="form-control" type="text" placeholder="Product Name" formControlName="ProductName" required/></td>
          <td><input class="form-control" type="number" step=".01" (focus)="$event.target.select()" placeholder="Quantity" formControlName="Quantity"/></td>
          <td><input class="form-control" readonly formControlName="UOM"></td>
          <td><date-picker formControlName="RequestedShipDate" format="L" [showClearButton]="false"></date-picker></td>
          <td><button type="button" (click)="deleteLineDetail(i)">Remove</button></td>
        </tr>
      </tbody>

4 个答案:

答案 0 :(得分:8)

我不会在这里使用valueChanges,它会被过度激发,特别是如果数组有很多值。

您可以对每个值进行更改事件,只需传递值和索引,例如

(keyup)="changeValue(line.controls.ProductName.value, i)"

但这种反应形式的目的。

即使你有很多你不希望在表单中显示的值,并且它是用户无法修改的值,我只是将它们作为表单控件添加到表单中,没有任何内容表明你需要在模板中显示它们!

这样,如果您以与模型order匹配的方式构建表单,则可以在提交时直接将表单值分配给模型。我强烈推荐这种方法。

答案 1 :(得分:4)

export class CustomFormArray {
     public form: FormGroup;

     public get someArray(): FormArray {
          return this.form.get('someArray') as FormArray
     }

     constructor(private _fb: FormBuilder) {
          this.form = _fb.group({
               someArray: _fb.array([])
          });

          this.someArray.controls.forEach(
               control => {
                   control.valueChanges.subscribe(
                        () => {
                       console.log(this.someArray.controls.indexOf(control)) // logs index of changed item in form array
                        }
                   )
               }
          )
     }
}    

答案 2 :(得分:0)

您可以为要在表单数组中维护的项目创建自己的组件。对于每次更新,删除等,您都会向父组件发出一个事件,并且您可以在绑定到父组件中的事件中发出该索引,或者您也可以在模板的父组件中拥有该索引以将其用作用于绑定子组件的change事件的函数的附加输入参数。

通读本文,您将了解我的意思:

https://medium.com/spektrakel-blog/angular2-building-nested-reactive-forms-7978ecd145e4

答案 3 :(得分:0)

我找到了一种方法来帮助想要查找更改值的元素的人

这是我的html

<mat-form-field>
   <mat-label>Material</mat-label>
   <mat-select formControlName="material" (ngModelChange)="materialChange($event)">
      <mat-option *ngFor="let objetct of materiais" [value]="objetct">   
        {{objetct?.nome}}
      </mat-option>
  </mat-select>
</mat-form-field>

这是我的Angular ts文件

@Component({
  selector: 'app-solicitar-material-form',
  templateUrl: './solicitar-material-form.component.html',
  styleUrls: ['./solicitar-material-form.component.css']
})
export class SolicitarMaterialFormComponent implements OnInit {

  public form: FormGroup;
  private object: SolicitacaoMaterialDTO;
  public materiais: MaterialDTO[] = [];

  @Output() mudouValor: EventEmitter<Unidade> = new EventEmitter();

  constructor() {
    this.form = new FormGroup({
      "itens": this.formBuilder.array([])
    });
  }

  ngOnInit() {
    this.getMateriais();
 }

  getMateriais() {
    this.materialService.findAll().subscribe((res) => {
      if (res) {
        this.materiais = res;
      }
    })
  }

  // this is the method that make me find the item that changed
  materialChange($event) {
    (<FormArray>this.form.get('itens')).controls.map((material) => {
      if (material.value.material == $event) {
        material.patchValue({
          unidadeMedida:$event.unidadeMedida
        });
      }
    });
  }

  get itens() {
    return this.form.get('itens') as FormArray;
  }

  clickAddItem() {
    this.itens.push(this.createItem());
  }

  createItem(): FormGroup {
    return this.formBuilder.group({
      material: this.formBuilder.control(null, [Validators.required]),
      unidadeMedida: this.formBuilder.control(null),
      quantidadeSolicitada: this.formBuilder.control(null, [Validators.required]),
    });
  }
}