I'm just learning Angular (actually started to learn web development a few months ago). I want to display data from a Form into a table. I have the following model:
export class Content {
id: number = 0;
title?: string;
subtitle?: string;
content?: string;
date?: string;
media?: string;
}
Then, I have a form with some methods as onSubmit()
that pushes data into an array.
onSubmit() {
if (this.selectedContent.id === 0) {
this.selectedContent.id = this.contentsList.length 1;
this.contentsList.push(this.selectedContent);
}
this.selectedContent = new Content();
this.notificationService.success('El postulante se creó correctamente');
console.log(this.contentsList);
}
When I console.log contentsList
it shows with the new data from the form, but it does not show in the table:
dataSource = this.contentsList;
columnsToDisplay = ['title', 'subtitle', 'body', 'date'];
expandedElement: Content | null | undefined;
THIS IS MY TABLE:
<table mat-table [dataSource]="dataSource" multiTemplateDataRows >
<ng-container matColumnDef="{{column}}" *ngFor="let column of columnsToDisplay">
<th mat-header-cell *matHeaderCellDef> {{column}} </th>
<td mat-cell *matCellDef="let content"> {{content[column]}} </td>
</ng-container>
<!-- Expanded Content Column - The detail row is made up of this one column that spans across all columns -->
<ng-container matColumnDef="expandedDetail">
<td mat-cell *matCellDef="let element[attr.colspan]="columnsToDisplay.length">
<div [@detailExpand]="element == expandedElement ? 'expanded' : 'collapsed'">
<div >
<div > {{content.title}} </div>
<div > {{content.subtitle}} </div>
<div > {{content.date}} </div>
<div > {{content.body}} </div>
</div>
<div >
{{content.body}}
<span > </span>
</div>
</div>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="columnsToDisplay"></tr>
<tr mat-row *matRowDef="let content; columns: columnsToDisplay;"
[class.example-expanded-row]="expandedElement === content" (click)="expandedElement = expandedElement === content ? null : content">
</tr>
<tr mat-row *matRowDef="let row; columns: ['expandedDetail']" ></tr>
</table>
I'm very sorry for my English, I'm from Argentina.
Thanks in advance.
CodePudding user response:
It might be you have used changeDetection
method in your component.
Please look at your ts file if you have ChangeDetectionStrategy
This is the example code.
@Component({
selector: 'test',
changeDetection: ChangeDetectionStrategy.OnPush,
templateUrl: './test.component.html',
styleUrls: ['test.component.scss'],
})
If you have change detection then there are two ways to fix this issue.
Simply remove the below line from your component ts file.
changeDetection: ChangeDetectionStrategy.OnPush
Please add the below code to your ts component file.
Import ChangeDetectorRef at the top of the ts file.
import { ChangeDetectorRef } from '@angular/core';
Add a reference to the constructor.
constructor(public changeDetectorRef: ChangeDetectorRef) { }
Add below the line at the end of onSubmit
method.
this.changeDetectorRef.detectChanges();
CodePudding user response:
Has no about changeDetectorRef. the problem with a MatTable is that if we add/remove/change an element of the datasource we need say that redraw the table again See the docs, in the API about DataSource
If a data array is provided, the table must be notified when the array's objects are added, removed, or moved. This can be done by calling the renderRows() function which will render the diff since the last table render. If the data array reference is changed, the table will automatically trigger an update to the rows
So, if you only has one table in your component you can use ViewChild to get the table
@ViewChild(MatTable) table:MatTable<any>
So, when you add the element you use this.table.renderRows()
.
if (this.selectedContent.id === 0) {
...
this.table.renderRows()
}
But you need take account another thing in your code. You use
//the code is WRONG
if (this.selectedContent.id === 0) {
this.contentsList.push(this.selectedContent);
}
this.selectedContent = new Content();
Is wrong because you are adding the same "object", you need make a "copy" of the object. If your object is a simple object, this copy can be make it using the spreadOperator, so the function becomes finally like
onSubmit() {
if (this.selectedContent.id === 0) {
this.selectedContent.id = this.contentsList.length 1;
//push a "copy of the object
this.contentsList.push({...this.selectedContent});
this.table.renderRows()
}
this.selectedContent = new Content();
}