我正在使用带有响应式形式的 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]
})
})
}
订单显然是我的反应式表单 FormGroup。 订单是我从 API 获得的对象,我想更新其值,包括行详细信息。我想我应该在每个新组上使用"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>
我不会在这里使用valueChanges
,它会过度触发,特别是如果数组有很多值。
您可以对每个值进行更改事件,然后只传递值和索引,例如
(keyup)="changeValue(line.controls.ProductName.value, i)"
但这种对抗反应形式的目的。
即使您有很多不想在表单中显示的值,并且是用户无法修改的值,我还是会将它们作为表单控件添加到表单中,没有说您需要在模板中显示它们!
这样,如果您以与您的模型order
匹配的方式构建表单,则可以在提交时直接将表单值分配给模型。我强烈推荐这种方法。
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
}
)
}
)
}
}
我找到了一种方法来帮助想要找到更改值的元素的人
这是我的网页
<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]),
});
}
}
您可以为要在表单数组中维护的项目创建自己的组件。对于每次更新、删除等,您都会向父组件发出一个事件,并且您可以使用在父组件中绑定的事件发出索引,或者您也可以在模板的父组件中将索引用作用于绑定子组件的更改事件的函数的附加输入参数。
通读这篇文章,你就会明白我的意思:
https://medium.com/spektrakel-blog/angular2-building-nested-reactive-forms-7978ecd145e4