I use a form array in my mat-table and would like to add a new row to the table by clicking the add button. I wrote the logic for this. But nothing is shown to me. Can you tell me where my mistake is and how I can fix it?
My Code:
// HTML
<!-- Add rows -->
<button type="submit" mat-raised-button (click)="addRow()">add</button>
<!-- Table-Content -->
<td mat-cell *matCellDef="let row; let i = index;">
<div formArrayName="rows" *ngIf="attributesWithFormControls.includes(column.attribute); else otherColumns">
<span class="edit-cell" [formGroupName]="i">
<mat-form-field>
<label>
<input matInput type="text" [formControlName]="column.attribute">
</label>
</mat-form-field>
</span>
</div>
<ng-template #otherColumns>
{{ column.object !== null ? row[column.object][column.attribute] : row[column.attribute] }}
</ng-template>
</td>
// TS
// For the form
calcBookingsForm: FormGroup;
// Variables for Data Table
public columns = [];
public dataSource: MatTableDataSource<MyModel> = null;
public displayedColumns: EditColumns[] = [
{ attribute: 'firstName', name: 'Firstname', object: null },
{ attribute: 'secondName', name: 'Lastname', object: null }
];
// Attributes defined here are displayed as input in the front end
public attributesWithFormControls = ['firstName', 'secondName'];
ngOnInit(): void {
this.columns = this.displayedColumns.map(c => c.attribute);
// CalcBookings form
this.calcBookingsForm = this.formBuilder.group({
rows: this.formBuilder.array([this.initItemRows()])
});
}
get formArr() {
return this.calcBookingsForm.get('rows') as FormArray;
}
initItemRows() {
return this.formBuilder.group({
firstName: [''],
lastName: [''],
});
}
// To add new row in the CalculatoryBookings
addRow() {
this.formArr.push(this.initItemRows())
}
Columns represent data types in rows, so adding a row to a table is like adding an empty record. It depends what you want to do with the data in a new row when entering the data you have to add another logic for the behavior of the row when saving the new data, in this example I am teaching how to add a new row. Html file with table and one button to add row:
<div style="margin-top: 64px; margin-left: 64px;">
<button (click)="AddRow()" mat-raised-button>Add</button>
</div>
<div style="margin-top: 64px;"></div>
<table mat-table [dataSource]="dataSource" multiTemplateDataRows class="mat-elevation-z8">
<ng-container matColumnDef="{{column}}" *ngFor="let column of columnsToDisplay">
<th mat-header-cell *matHeaderCellDef> {{column}} </th>
<td mat-cell *matCellDef="let element">
<mat-form-field>
<input matInput [value]="element[column]" />
</mat-form-field>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="columnsToDisplay"></tr>
<tr mat-row *matRowDef="let element; columns: columnsToDisplay;">
</tr>
</table>
Class with data that You want to add:
export interface ProductElement {
name: string;
id: string;
color: string;
year: number;
price: number;
}
Data to create rows with example data:
// List of Brands
brands: string[] = ['Vapid', 'Carson', 'Kitano', 'Dabver', 'Ibex', 'Morello', 'Akira', 'Titan', 'Dover', 'Norma'];
// List of Colors
colors: string[] = ['Black', 'White', 'Red', 'Blue', 'Silver', 'Green', 'Yellow'];
// Column definition
columnsToDisplay: string[] = ['id', 'name', 'year', 'color', 'price'];
dataSource: MatTableDataSource<ProductElement>;
Method for create random data:
generateName = () => {
return this.brands[Math.floor(Math.random() * Math.floor(10))];
}
generatePrice = () => {
return Math.floor(Math.random() * Math.floor(50000) + 1);
}
generateColor = () => {
return this.colors[Math.floor(Math.random() * Math.floor(7))];
}
generateYear = () => {
return 2000 + Math.floor(Math.random() * Math.floor(19));
}
createId(): string {
let id = '';
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
for (let i = 0; i < 5; i++) {
id += chars.charAt(Math.floor(Math.random() * chars.length));
}
return id;
}
method to add new row:
newRow = () => {
const data = {
id: this.createId(),
name: this.generateName(),
year: this.generateYear(),
color: this.generateColor(),
price: this.generatePrice(),
};
return data;
}
and method to add new row with sample data.
AddRow(): void {
ELEMENT_DATA.push(this.newRow());
this.dataSource = new MatTableDataSource<ProductElement>(ELEMENT_DATA);
}
Practice with this and you will tell me how it goes. Update: in You example if You change Add method like below its work Result: