23

我正在使用带有反应形式的 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 获得的对象,我想更新它的值,包括行详细信息。我认为我应该在每个 newGroup 上使用“valueChanges.subscribe”,但我不确定如何获取已更改项目的索引。有什么想法吗?

     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

4 回答 4

15

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

您可以对每个值都有一个更改事件,然后只传递值和索引,例如

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

但是这种对抗反应形式的目的。

即使您有很多不想在表单中显示的值,并且这些值是用户无法修改的,我还是将它们作为表单控件添加到表单中,没有什么说您需要在其中显示它们模板!

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

于 2017-07-14T13:18:40.987 回答
11
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
                        }
                   )
               }
          )
     }
}    
于 2017-09-06T14:36:40.187 回答
1

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

这是我的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]),
    });
  }
}
于 2020-04-16T22:10:45.457 回答
0

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

通读这篇文章,你就会明白我的意思:

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

于 2018-12-06T13:09:18.747 回答