I am new to angularCLI. In this case, I want to create a table with the dataSource is retrieved from an API (fake APIs).
Here is my component class:
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
import { Blog, MyapiService } from 'src/app/services/myapi.service';
@Component({
selector: 'app-blogs-put',
templateUrl: './blogs-put.component.html',
styleUrls: ['./blogs-put.component.css']
})
export class BlogsPutComponent implements OnInit {
updateForm!: FormGroup;
myArr = [
{id: 11, title: 'MyTitle1', body: 'MyBody1'},
{id: 12, title: 'MyTitle2', body: 'MyBody2'},
{id: 13, title: 'MyTitle3', body: 'MyBody3'},
{id: 14, title: 'MyTitle4', body: 'MyBody4'},
{id: 15, title: 'MyTitle5', body: 'MyBody5'},
]
// table
blogs: Blog[] = [];
displayedColumns: string[] = ['id', 'title'];
dataSource = this.myArr;
constructor(
private apiS: MyapiService,
private fb: FormBuilder
) { }
ngOnInit(): void {
this.getBlogs();
this.updateForm = this.fb.group({
Utitle: new FormControl('', Validators.required),
Ubody: new FormControl('', Validators.required)
})
}
pushBlog(){
console.log(JSON.stringify(this.blogs))
}
getBlogs(){
this.apiS.getBlog().subscribe(data => {
this.blogs = data
})
}
onSubmit(){
console.log(this.updateForm.value)
}
injectData(){
let newData = {
Utitle: 'Lorem Ipsum',
Ubody: 'Lorem ipsum dolor sit amet consectetur adipisicing elit. Fuga repellendus accusantium, quod cupiditate deleniti soluta cum voluptate quibusdam ut laborum ipsum praesentium earum reprehenderit delectus natus adipisci suscipit eum excepturi!'
}
this.updateForm.setValue(newData)
}
}
And here's my template:
<div class="container">
<div class="row">
<mat-card class="full-width">
<mat-card-title>Blogs list</mat-card-title>
<mat-card-content>
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
<ng-container matColumnDef="id">
<th mat-header-cell *matHeaderCellDef>Id</th>
<td mat-cell *matCellDef="let blog">{{blog.id}}</td>
</ng-container>
<ng-container matColumnDef="title">
<th mat-header-cell *matHeaderCellDef>Title</th>
<td mat-cell *matCellDef="let blog">{{blog.title}}</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
</table>
</mat-card-content>
</mat-card>
</div>
</div>
If I assign the dataSource with this.blogs (which is an APIs get data), the table content wouldn't be loaded. But if I use this.myArr which is a local data, it loaded successfully in the table template.
Any helps would be really appreciated :)
According to Angular Material Table documentation,
While an array is the simplest way to bind data into the data source, it is also the most limited. For more complex applications, using a DataSource instance is recommended. See the section "Advanced data sources" below for more information.
Hence, it is recommended to pass [dataSource]
Input property with the value of MatTableDataSource
type.
The solution should be as below:
blogs-put.component.html (Only provide with mat-table HTML element)
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
<ng-container matColumnDef="id">
<th mat-header-cell *matHeaderCellDef>Id</th>
<td mat-cell *matCellDef="let blog">{{blog.id}}</td>
</ng-container>
<ng-container matColumnDef="title">
<th mat-header-cell *matHeaderCellDef>Title</th>
<td mat-cell *matCellDef="let blog">{{blog.title}}</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
</table>
blogs-put.component.ts
import { MatTableDataSource } from '@angular/material/table';
@Component({
selector: 'app-blogs-put',
templateUrl: './blogs-put.component.html',
styleUrls: ['./blogs-put.component.css']
})
export class BlogsPutComponent implements OnInit {
..
dataSource: MatTableDataSource<Blog>;
constructor(private apiS: MyapiService, private fb: FormBuilder) {
this.dataSource = new MatTableDataSource<Blog>();
}
..
getBlogs() {
this.apiS.getBlog().subscribe(data => {
this.blogs = data;
this.dataSource = new MatTableDataSource(this.blogs);
});
}
}
EDITED:
In case you get this warning message below:
"Property 'dataSource' has no initializer and is not definitely assigned in the constructor."
This is due to strictPropertyInitialization
is enabled in tsconfig.json. Hence you can solve this issue by initializing the value in constructor
or ngOnInit
methods.
You may refer to: Property '…' has no initializer and is not definitely assigned in the constructor.