I'm using Angular-Material and the component of mat-table, I'm trying to create a form to set some concepts to create a bill, but when I make the first push to the formArray this throws an error in the console, that says:
ERROR Error: Cannot find control with name: 'partidaDetailLibre'
this is how I make the push to the form since component
datosFacturaLibre = this.formBuilder.group({
concepts: this.formBuilder.array([]),
})
get newPartidaLibre(): FormGroup {
return this.formBuilder.group({
claveSat: [''],
claveUnidadSat: [''],
unidad: [''],
quantity: [''],
description: [''],
totalCostFinalAmount: [''],
totalCostFinalAmountWithCurrency: [''],
subtotal: [''],
subtotalWithCurrency: [''],
totalIva: [''],
totalIvaWithCurrency: [''],
total: [''],
totalWithCurrency: [''],
})
}
get partidaDetailLibre(): FormArray {
return this.datosFacturaLibre.get('concepts') as FormArray;
}
async addPartidaLibre() {
await this.partidaDetailLibre.push(this.newPartidaLibre);
}
And in the HTML I got as this
<form [formGroup]="datosFacturaLibre" autocomplete="off">
<mat-card>
<section style="padding: 10px" *ngIf="tipoFacturacion">
<mat-horizontal-stepper [linear]="isLinear">
<mat-step label="Agregar conceptos">
<div formArrayName="partidaDetailLibre">
<div class="mat-elevation-z8" style="padding: 10px">
<table mat-table [dataSource]="partidaDetailLibre.controls">
<!-- claveSat Column -->
<ng-container matColumnDef="number">
<th mat-header-cell *matHeaderCellDef style="text-align: center; padding-right: 15px; padding-left: 15px"> # </th>
<td mat-cell *matCellDef="let row; index as i" [formGroup]="row"
style="text-align: center; padding-right: 15px; padding-left: 15px">
{{i+1}}
</td>
</ng-container>
<!-- claveSat Column -->
<ng-container matColumnDef="claveSat">
<th mat-header-cell *matHeaderCellDef style="text-align: center"> Clave SAT
</th>
<td mat-cell *matCellDef="let row; index as i" style="text-align: center"
[formGroup]="row">
<input type="text" matInput
(keyup)="getClaveSat($event.target.value); filterClaveSat($event.target.value)"
formControlName="claveSat" [matAutocomplete]="autoClaveSat" style="border-bottom: 1px solid; width: 60px;"/>
<mat-autocomplete #autoClaveSat [panelWidth]="300">
<mat-option (click)="changeClaveSat(claveSat, i)"
(onSelectionChange)="changeClaveSat(claveSat, i)"
*ngFor="let claveSat of filteredClaveSat" [value]="claveSat">
{{claveSat.c_claveprodserv}} - {{claveSat.descripcion}}
</mat-option>
</mat-autocomplete>
</td>
</ng-container>
<!-- claveUnSat Column -->
<ng-container matColumnDef="claveUnSat">
<th mat-header-cell *matHeaderCellDef style="text-align: center"> Clave de
unidad
</th>
<td mat-cell *matCellDef="let row; index as i" style="text-align: center"
[formGroup]="row">
<input type="text" matInput
(keyup)="getClaveUnidadSat($event.target.value); filterClaveUnidadSat($event.target.value)"
formControlName="claveUnidadSat" [matAutocomplete]="autoClaveUnidadSat" style="border-bottom: 1px solid; width: 60px;"/>
<mat-autocomplete #autoClaveUnidadSat [panelWidth]="300">
<mat-option (click)="changeClaveUnidadSat(claveUnidadSat, i)"
(onSelectionChange)="changeClaveUnidadSat(claveUnidadSat, i)"
*ngFor="let claveUnidadSat of filteredClaveUnidadSat"
[value]="claveUnidadSat">
{{claveUnidadSat.c_claveunidad}} - {{claveUnidadSat.nombre}}
</mat-option>
</mat-autocomplete>
</td>
</ng-container>
<!-- unidad Column -->
<ng-container matColumnDef="unidad">
<th mat-header-cell *matHeaderCellDef style="text-align: center"> Unidad
</th>
<td mat-cell *matCellDef="let row" style="text-align: center" [formGroup]="row">
<input matInput formControlName="unidad"
style="height: 28px; text-align: center;" style="border-bottom: 1px solid; width: 60px;">
</td>
</ng-container>
<!-- concepto Column -->
<ng-container matColumnDef="concepto">
<th mat-header-cell *matHeaderCellDef style="text-align: center"> Concepto
</th>
<td mat-cell *matCellDef="let row" style="text-align: center" [formGroup]="row">
<input matInput formControlName="description"
style="height: 28px; text-align: center;" style="border-bottom: 1px solid; width: 60px;">
</td>
</ng-container>
<!-- cantidad Column -->
<ng-container matColumnDef="cantidad">
<th mat-header-cell *matHeaderCellDef style="text-align: center"> Cantidad
</th>
<td mat-cell *matCellDef="let row" style="text-align: center" [formGroup]="row">
<input matInput formControlName="quantity"
style="height: 28px; text-align: center;" style="border-bottom: 1px solid; width: 60px;">
</td>
</ng-container>
<!-- precioUnitario Column -->
<ng-container matColumnDef="precioUnitario">
<th mat-header-cell *matHeaderCellDef style="text-align: center"> Precio
Unitario
</th>
<td mat-cell *matCellDef="let row" style="text-align: center" [formGroup]="row">
<input matInput formControlName="totalCostFinalAmountWithCurrency"
style="height: 28px; text-align: center;" style="border-bottom: 1px solid; width: 60px;">
</td>
</ng-container>
<!-- iva Column -->
<ng-container matColumnDef="iva">
<th mat-header-cell *matHeaderCellDef style="text-align: center"> IVA </th>
<td mat-cell *matCellDef="let row" style="text-align: center" [formGroup]="row">
<input matInput formControlName="totalIvaWithCurrency"
style="height: 28px; text-align: center;" style="border-bottom: 1px solid; width: 60px;">
</td>
</ng-container>
<!-- total Column -->
<ng-container matColumnDef="total">
<th mat-header-cell *matHeaderCellDef style="text-align: center"> Total
</th>
<td mat-cell *matCellDef="let row" style="text-align: center" [formGroup]="row">
<input matInput formControlName="totalWithCurrency"
style="height: 28px; text-align: center;" style="border-bottom: 1px solid; width: 60px;">
</td>
</ng-container>
<!-- total Column -->
<ng-container matColumnDef="acciones">
<th mat-header-cell *matHeaderCellDef style="text-align: center"> Acciones
</th>
<td mat-cell *matCellDef="let row" style="text-align: center"> acciones
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="columnsConceptsLibre"></tr>
<tr mat-row *matRowDef="let row; columns: columnsConceptsLibre;"></tr>
</table>
<div fxLayout="row" fxLayoutAlign="end center" style="margin-top: 16px">
<table mat-table class="tbtotal" style="width: 40%;"
[dataSource]="dataSourceConceptsTotals">
<ng-container matColumnDef="concepto">
<th mat-header-cell *matHeaderCellDef>Concepto</th>
<td mat-cell *matCellDef="let element">
{{element.concept}}</td>
</ng-container>
<ng-container matColumnDef="monto">
<th mat-header-cell *matHeaderCellDef>Monto</th>
<td mat-cell *matCellDef="let element">
{{element.amount | currency}}</td>
</ng-container>
<ng-container matColumnDef="moneda">
<th mat-header-cell *matHeaderCellDef>Moneda</th>
<td mat-cell *matCellDef="let element">
{{element.currency}}</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="columnsConceptsTotalsLibre; sticky: true">
</tr>
<tr mat-row *matRowDef="let row; columns: columnsConceptsTotalsLibre;"></tr>
</table>
</div>
</div>
</div>
</mat-step>
<mat-step label="Timbrar">
<p>Segundo step</p>
</mat-step>
</mat-horizontal-stepper>
</section>
</mat-card>
</form>
I have a slide toggle to show or hide the form, when I make it appear, in the stackblitz example it does not take much time, but on my pc it does
hope someone can help me to know how I can reduce the time taken to show the form and get rid of the console error
1 Answer
The console error:
Error: Cannot find control with name: 'partidaDetailLibre'
It means that you haven't defined a FormArray with this name. In your code I can see:
datosFacturaLibre = this.formBuilder.group({
concepts: this.formBuilder.array([]),
});
and
get partidaDetailLibre(): FormArray {
return this.datosFacturaLibre.get('concepts') as FormArray;
}
Change concepts with partidaDetailLibre. It solves the error.
On the other hand, why are you checking twice tipoFacturacion?
<form
[formGroup]="datosFacturaLibre"
autocomplete="off"
*ngIf="tipoFacturacion"
>
<mat-card>
<section style="padding: 10px" *ngIf="tipoFacturacion">
<mat-horizontal-stepper [linear]="isLinear">
<mat-step label="Agregar conceptos">
<div formArrayName="partidaDetailLibre">
......
It's not neccessary. Remove the second one.
If you want to show and hide the form, change the method of the in this way:
cambioTipoFacturacion() {
this.tipoFacturacion = !this.tipoFacturacion;
}
Here the Stackblitz with your code and the changes: