11

My simple task is to add the text typed in an input box to the mat-table but it didn't work as expected. The datasource only refreshed one time and didn't show update data start from the second time.

Here is my code app.component.html

 <div class="main" fxLayout="column" fxGap="10">
 <div class="input-area">
 <mat-form-field>
 <input matInput placeholder="Type something" [(ngModel)]="currentText"> 
 </mat-form-field>
 <button mat-raised-button color="primary" style="margin-left:10px;" (click)="onAdd($event)">Add</button>
 </div>
 <div class="result-area">
 <mat-table #table [dataSource]="dataSource" class="mat-elevation-z8">
 <ng-container matColumnDef="name">
 <mat-header-cell #th *matHeaderCellDef> Name </mat-header-cell>
 <mat-cell #td *matCellDef="let element"> {{element.name}} </mat-cell>
 </ng-container>
 <mat-header-row #tr *matHeaderRowDef="displayedColumns"></mat-header-row>
 <mat-row #tr *matRowDef="let row; columns: displayedColumns;"></mat-row>
 </mat-table>
 </div>

This is my "app.component.ts" which contains "Add" event that updates the table datasource.

@Component({
 selector: 'my-app',
 templateUrl: './app.component.html',
 styleUrls: [ './app.component.css' ]
})
export class AppComponent {
 currentText: string= "";
 displayedColumns = ['name'];
 data: Data[] = [];
 dataSource: Data[];
 constructor(){}
 onAdd($event){
 this.data.push({name: this.currentText});
 this.dataSource = this.data;
 }
}
interface Data{
 name: string;
}

What did I do wrong? Here is the stackblitz example of the above code

A-Sharabiani
19.6k22 gold badges129 silver badges140 bronze badges
asked Jun 14, 2018 at 3:08

4 Answers 4

32

Reference to dataSource remains the same so that material doesn't know that your source changed.

Try

this.dataSource = [...this.data];

Forked Stackblitz

Or use BehaviorSubject like:

dataSource = new BehaviorSubject([]);
onAdd($event){
 this.data.push({name: this.currentText});
 console.log(this.data);
 this.dataSource.next(this.data);
}

Forked Stackblitz

answered Jun 14, 2018 at 3:27
Sign up to request clarification or add additional context in comments.

3 Comments

Btw you can improve by this.dataSource.next([ ...this.dataSource.getValue, ...[{name: this.currentText}]]);
Good to know this
@Volodymyr Bilyachat Glad to know you know how improve it. I've just showed right direction
12

Instead of push use concat to let table know that you modified the object

 this.data = this.data.concat([{name: this.currentText}]);
answered Jun 14, 2018 at 3:24

2 Comments

Why somebody minus this one? does that one understand a difference between push and concat ?:)
@Alexandre nothing weird angular will compare data by reference
0

May you can rebuild the table with new data.

this.tableData = this.dataSource.data;
this.dataSource.data = this.tableData.push(newRecord);
this.dataSource = new MatTableDataSource<any>(this.tableData);
answered Apr 17, 2020 at 4:00

Comments

-2

just hide the table till the data shows up then show. Simple but it works. I use *ngIf="...", and Angular for this.

answered Nov 25, 2019 at 16:55

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.