如何获取 angular 表单数组中已更改项目的索引
How to get index of changed item in angular form array
我正在使用 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>
我不会在这里使用 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
}
)
}
)
}
}
您可以为要在表单数组中维护的项目创建自己的组件。对于每次更新、删除等,您都会向父组件发出一个事件,您可以使用您在父组件中绑定的事件发出的索引,或者您在模板中的父组件中也有索引以将其用作用于绑定子组件更改事件的函数的附加输入参数。
看完这篇文章你就会明白我的意思了:
https://medium.com/spektrakel-blog/angular2-building-nested-reactive-forms-7978ecd145e4
我找到了一个方法来帮助那些想要找到改变值的元素的人
这是我的 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]),
});
}
}
我正在使用 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>
我不会在这里使用 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
}
)
}
)
}
}
您可以为要在表单数组中维护的项目创建自己的组件。对于每次更新、删除等,您都会向父组件发出一个事件,您可以使用您在父组件中绑定的事件发出的索引,或者您在模板中的父组件中也有索引以将其用作用于绑定子组件更改事件的函数的附加输入参数。
看完这篇文章你就会明白我的意思了:
https://medium.com/spektrakel-blog/angular2-building-nested-reactive-forms-7978ecd145e4
我找到了一个方法来帮助那些想要找到改变值的元素的人
这是我的 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]),
});
}
}