嵌套表单组多次触发变更检测
Nested Form Group triggeres change detection multiple times
使用 作为参考,我已经复制了使用反应式表单创建的动态嵌套表单组。
但在将新的表单组添加到表单数组时,它会多次触发更改检测。
my code
component.html
<button mat-flat-button color="primary" (click)="addMaterial()">Add</button>
<form [formGroup]="positionFormGroup" novalidate>
<table formArrayName="positionInfos">
<div *ngFor="let data of Controls.controls; let i = index">
<div [formGroupName]="i">
<input type="text" formControlName="idMaterial" [matAutocomplete]="materialAuto">
<mat-autocomplete #materialAuto="matAutocomplete">
<mat-option *ngFor="let option of materialFilteredOptions | async" [value]="option.description">
{{option.description}}
</mat-option>
</mat-autocomplete>
</div>
</div>
</table>
</form>
component.ts
export class AppComponent {
positionFormGroup: FormGroup;
materialControl: FormControl = new FormControl('');
materialFilteredOptions: Observable<{ description: string; }[]>;
options = [
{ description: 'item1' },
{ description: 'item2' },
{ description: 'item3' },
{ description: 'item4' }
]
constructor(private formBuilder: FormBuilder) {
}
ngOnInit(): void {
this.materialFilteredOptions = this.materialControl.valueChanges
.pipe(
startWith(''),
map(value => this.options)
);
this.positionFormGroup = this.formBuilder.group({
positionInfos: new FormArray([])
});
this.addMaterial();
}
ngDoCheck(){
console.log('triggered');
}
addMaterial() {
(this.positionFormGroup.get('positionInfos') as FormArray).push(this.formBuilder.group({
rowID: '0',
position: '0',
idMaterial: 'item1',
quantity: 1,
isDeleted: false,
isActive: true
}));
}
confirm(){
console.log( this.positionFormGroup.get('positionInfos').value)
}
get Controls(){
console.log( (this.positionFormGroup.get('positionInfos') as FormArray));
return (this.positionFormGroup.get('positionInfos') as FormArray);
}
}
也共享了控制台。当我将新的表单组添加到表单数组时,它正在发生。
我不明白为什么它会多次触发变化检测。
如果我遗漏了什么,请告诉我。提前致谢
我应该将 ChangeDetectionStrategy 更改为 onPush,这样组件只会渲染一次
@Component({
selector: "hello",
templateUrl: "./hello.component.html",
changeDetection: ChangeDetectionStrategy.OnPush,
})
经过一番研究,我得到了答案。每当发生变化检测时,模板都会重新评估该方法。
不用控件getter,直接用class属性得到嵌套表单组控件
ts
this.control = this.getControls().controls;
getControls(){
console.log( (this.positionFormGroup.get('positionInfos') as FormArray));
return (this.positionFormGroup.get('positionInfos') as FormArray);
}
html
<div *ngFor="let data of control; let i = index">
使用
但在将新的表单组添加到表单数组时,它会多次触发更改检测。
my code
component.html
<button mat-flat-button color="primary" (click)="addMaterial()">Add</button>
<form [formGroup]="positionFormGroup" novalidate>
<table formArrayName="positionInfos">
<div *ngFor="let data of Controls.controls; let i = index">
<div [formGroupName]="i">
<input type="text" formControlName="idMaterial" [matAutocomplete]="materialAuto">
<mat-autocomplete #materialAuto="matAutocomplete">
<mat-option *ngFor="let option of materialFilteredOptions | async" [value]="option.description">
{{option.description}}
</mat-option>
</mat-autocomplete>
</div>
</div>
</table>
</form>
component.ts
export class AppComponent {
positionFormGroup: FormGroup;
materialControl: FormControl = new FormControl('');
materialFilteredOptions: Observable<{ description: string; }[]>;
options = [
{ description: 'item1' },
{ description: 'item2' },
{ description: 'item3' },
{ description: 'item4' }
]
constructor(private formBuilder: FormBuilder) {
}
ngOnInit(): void {
this.materialFilteredOptions = this.materialControl.valueChanges
.pipe(
startWith(''),
map(value => this.options)
);
this.positionFormGroup = this.formBuilder.group({
positionInfos: new FormArray([])
});
this.addMaterial();
}
ngDoCheck(){
console.log('triggered');
}
addMaterial() {
(this.positionFormGroup.get('positionInfos') as FormArray).push(this.formBuilder.group({
rowID: '0',
position: '0',
idMaterial: 'item1',
quantity: 1,
isDeleted: false,
isActive: true
}));
}
confirm(){
console.log( this.positionFormGroup.get('positionInfos').value)
}
get Controls(){
console.log( (this.positionFormGroup.get('positionInfos') as FormArray));
return (this.positionFormGroup.get('positionInfos') as FormArray);
}
}
也共享了控制台。当我将新的表单组添加到表单数组时,它正在发生。 我不明白为什么它会多次触发变化检测。
如果我遗漏了什么,请告诉我。提前致谢
我应该将 ChangeDetectionStrategy 更改为 onPush,这样组件只会渲染一次
@Component({
selector: "hello",
templateUrl: "./hello.component.html",
changeDetection: ChangeDetectionStrategy.OnPush,
})
经过一番研究,我得到了答案。每当发生变化检测时,模板都会重新评估该方法。
不用控件getter,直接用class属性得到嵌套表单组控件
ts
this.control = this.getControls().controls;
getControls(){
console.log( (this.positionFormGroup.get('positionInfos') as FormArray));
return (this.positionFormGroup.get('positionInfos') as FormArray);
}
html
<div *ngFor="let data of control; let i = index">