typescript - Angular UI fryser när man använder formArray med Material Auto-complete inuti Mat-table
Jag använder en mat-table inuti en popup. Inuti mat-tabellen kommer det att finnas rader med mat-autocomplete. Saken är den att jag behöver lägga till rader dynamiskt. Jag använder ett formGroup inuti vilket det finns en formArray.
detta kommer att vara modellen för FormGroup
{
formArray:
[
{
name:"someName",
material:"someMaterial",
quantity:5
},
{
name:"someName2",
material:"someMaterial",
quantity:5
},
]
}
Först kommer rutnätet att vara tomt men när jag klickar på en knapp, infogar det en formGroup i formArray (som är datakälla för rutnätet). Men när det händer fryser användargränssnittet helt och jag kan inte göra någonting.
här är HTML-filen Kod
<form [formGroup]="positionFormGroup">
<div class="card-body" style="height: 500px; overflow: auto;" >
<table class="full-width" style="overflow: scroll;" mat-table [dataSource]="this.positionFormGroup.get('positionInfos').value" formArrayName = "positionInfos">
<!-- Material Column -->
<ng-container matColumnDef="Material">
<th mat-header-cell *matHeaderCellDef class="text-center align-column">
<p [innerHTML]=" 'MachineCapacity.Grid_Label_IdMaterial' | translate"></p>
</th>
<td mat-cell *matCellDef="let data; let i = index" [formGroupName]="i">
{{data.idMaterial}}
<input type="text" formControlName="idMaterial" [matAutocomplete]="materialAuto">
<mat-autocomplete #materialAuto="matAutocomplete">
<mat-option *ngFor="let option of materialFilteredOptions | async" [value]="option.description"
class="auto-option">
{{option.description}}
</mat-option>
</mat-autocomplete>
</td>
</ng-container>
<!-- Quantity Column -->
<ng-container matColumnDef="Quantity">
<th mat-header-cell *matHeaderCellDef class="text-center align-column">
<p [innerHTML]=" 'MachineCapacity.Grid_Label_Quantity' | translate"></p>
</th>
<td mat-cell *matCellDef="let data">
{{data.quantity}}
</td>
</ng-container>
Jag kan spåra problemet. Det händer på grund av referensen jag använder för mat-auto complete. Det fungerar antingen när jag tar bort matAutoComplete-referensen från input-taggen eller när jag ändrar formControlName.
här är TS-koden :
ngOnInit(): void {
// this.positionInfos = new FormArray([]);
this.positionFormGroup = this.formBuilder.group({
positionInfos: new FormArray([])
});
//this.positionFormGroup.
}
addMaterial(){
let data = {
rowID :'f',
position : 'f',
idMaterial:'f',
quantity: 'f',
isDeleted: 'f',
isActive:true
}
this.positionFormGroup.get('positionInfos')?.push(this.formBuilder.group(data))
//console.log( this.positionFormGroup.get('positionInfos').value)
}
Vänligen låt mig veta om jag missar något, tack på förhand
Svar #1
Inte relaterat till referensproblemet och UI fryser inte alls.
Det hände på grund av ändringsdetektering, tror jag. Därför kände vi av en frusning i användargränssnittet.
Precis vid denna punkt, [dataSource]="this.positionFormGroup.get('positionInfos').value" triggar det ändringsdetekteringen oändligt många gånger
Jag vet inte, varför det utlöste oändligt många gånger.
Har redan ett svar för inbäddade formulärgrupper.
html
<form [formGroup]="positionFormGroup" novalidate>
<table formArrayName="positionInfos">
<div *ngFor="let data of control; 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>
ts
export class AppComponent {
positionFormGroup: FormGroup;
materialControl: FormControl = new FormControl('');
materialFilteredOptions: Observable<{ description: string; }[]>;
options = [
{ description: 'item1' },
{ description: 'item2' },
{ description: 'item3' },
{ description: 'item4' }
]
control: any;
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();
this.control = this.getControls().controls;
}
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)
}
getControls(){
console.log( (this.positionFormGroup.get('positionInfos') as FormArray));
return (this.positionFormGroup.get('positionInfos') as FormArray);
}
