I am getting an array from my restservice. This is working and some information of the response I am printing on the page. But strangely I cannot fill my mat-table and I don't know why.The mat-table was working before, I am just not putting the data in it the right way. Every help will be appreciated.
table-paginator-component.ts:
import {Component, OnInit, ViewChild} from '#angular/core';
import {MatPaginator} from '#angular/material/paginator';
import {MatTableDataSource} from '#angular/material/table';
import {HttpService} from '../http.service';
import { HttpClient } from '#angular/common/http';
import {AreaCode} from '../models/areacode';
#Component({
// tslint:disable-next-line: component-selector
selector: 'table-paginator',
styleUrls: ['table-paginator.component.css'],
templateUrl: 'table-paginator.component.html',
})
export class TablePaginatorComponent implements OnInit {
displayedColumns: string[] = ['standort', 'stammnummer', 'bereich'];
products = [];
dataSource = new MatTableDataSource<any>(this.products);
constructor(private httpClient: HttpClient) {
this.getAreaCodes();
}
#ViewChild(MatPaginator, {static: true}) paginator: MatPaginator;
ngOnInit() {
this.dataSource.paginator = this.paginator;
}
getAreaCodes() {
this.httpClient.get('http://localhost:8080/phonenumbersmanagement/api/v1/areacodes/all')
.subscribe((res:
any[]) => {
console.log(res);
this.products = res;
});
}
}
table-paginator.component.html:
<!-- <button (click)="getAreaCodes2()">GET /productss</button> -->
<ul>
<li *ngFor="let product of products" >
-- id: {{product.id}}
-- name: {{product.title}}
-- base: {{product.base}}
</li>
</ul>
<div class="mat-elevation-z8">
<table mat-table [dataSource]="dataSource">
<!-- Position Column -->
<ng-container matColumnDef="standort">
<th mat-header-cell *matHeaderCellDef> Standort </th>
<td mat-cell *matCellDef="let element"> {{element.title}} </td>
</ng-container>
<!-- Name Column -->
<ng-container matColumnDef="stammnummer">
<th mat-header-cell *matHeaderCellDef> Stammnummer </th>
<td mat-cell *matCellDef="let element"> {{element.title}} </td>
</ng-container>
<!-- Weight Column -->
<ng-container matColumnDef="bereich">
<th mat-header-cell *matHeaderCellDef> Bereich </th>
<td mat-cell *matCellDef="let element"> {{element.title}} </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
<mat-paginator [pageSizeOptions]="[5, 10, 20]" showFirstLastButtons></mat-paginator>
</div>
Current Output:
try with this.products = res;
this.datasource.data = res;
Change your getAreaCodes method like below,
getAreaCodes() {
this.httpClient.get('http://localhost:8080/phonenumbersmanagement/api/v1/areacodes/all')
.subscribe((res: any[]) => {
this.products = res;
this.dataSource = new MatTableDataSource(res);
});
}
Update your mat-paginator with length as like property binding.
<mat-paginator [length]="products.length" [pageSizeOptions]="[5, 10, 20]" showFirstLastButtons></mat-paginator>
I think that, when you receive data from api and add result value to products variable then datasource variable dont update.
Try to use products variable on html table tag-> [dataSource]="products"
This thing worked for me. import table from angular/material and create an
instance of it using viewchild. get your user data and set displayedColumns in ngOnInit(), In ngAfterContentChecked() you need to create MatTableDataSource instance and set this instance to table.dataSource in ngAfterViewInit() check below
import { MatTable, MatTableDataSource } from '#angular/material/table';
export class GetUserComponent implements OnInit {
#ViewChild(MatTable, {static:false}) table: MatTable<any>;
dataSource :any;
constructor(private appService:AppService){}
ngOnInit() {
this.appService.getUsers().subscribe(data => {
this.userData= data;
});
this.displayedColumns = ['select','title','content'];
}
ngAfterViewInit() {
this.table.dataSource = this.dataSource;
}
ngAfterContentChecked(){
this.dataSource = new MatTableDataSource (this.userData);
}
}
you can check my stackblitz here
https://stackblitz.com/edit/angular-dynamicexamples
Related
I am receiving an object when I enter console.log(data) but undefined
when I enter console.log(items). I am trying to enter the data in the
interface then display the entries in the table.
component.ts
import {HttpClient} from '#angular/common/http';
import {Component, ViewChild, AfterViewInit} from '#angular/core';
import {MatPaginator} from '#angular/material/paginator';
import {MatSort, SortDirection} from '#angular/material/sort';
import {merge, Observable, of as observableOf} from 'rxjs';
import {catchError, map, startWith, switchMap} from 'rxjs/operators';
import { MatTable } from '#angular/material/table';
import { AssetTableDataSource, AssetTableItem } from './asset-table-datasource';
import { AssetTableModule } from './asset-table.module';
#Component({
selector: 'app-asset-table',
templateUrl: './asset-table.component.html',
styleUrls: ['./asset-table.component.scss']
})
export class AssetTableComponent implements AfterViewInit {
displayedColumns: string[] = ['client_id','periodenddate', 'dataitemname', 'dataitemvalue'];
assetDatabase!: AssetRecHttpDatabase | null;
data: ClientidAssetData[] = [];
items: any[] =[];
resultsLength = 0;
isLoadingResults = true;
isRateLimitReached = false;
#ViewChild(MatPaginator)
paginator!: MatPaginator;
#ViewChild(MatSort)
sort!: MatSort;
constructor(private _httpClient: HttpClient) {}
ngAfterViewInit() {
this.assetDatabase = new AssetRecHttpDatabase(this._httpClient);
// If the user changes the sort order, reset back to the first page.
this.sort.sortChange.subscribe(() => (this.paginator.pageIndex = 0));
merge(this.sort.sortChange, this.paginator.page)
.pipe(
startWith({}),
switchMap(() => {
this.isLoadingResults = true;
return this.assetDatabase!.getAssetresults(
this.sort.active,
this.sort.direction,
this.paginator.pageIndex,
).pipe(catchError(() => observableOf(null)));
}),
map(data => {
// Flip flag to show that loading has finished.
this.isLoadingResults = false;
this.isRateLimitReached = data === null;
if (data === null) {
return [];
}
// Only refresh the result length if there is new data. In case of rate
// limit errors, we do not want to reset the paginator to zero, as that
// would prevent users from re-triggering requests.
this.resultsLength = data.total_count;
console.log(data);
console.log(data.items);
return data;
}),
)
.subscribe(data => (data = data));
}
}
export interface GetAssetApi {
items: ClientidAssetData[];
total_count: number;
}
export interface ClientidAssetData{
Clientid: string;
PeriodEndDate: string;
DataItemName: string;
DataItemValue: string;
}
/** The database that the data source uses to retrieve data for the table. */
export class AssetRecHttpDatabase {
constructor(private _httpClient: HttpClient) {}
getAssetresults(sort: string, order: SortDirection, page: number): Observable<GetAssetApi> {
const href = 'http://localhost:3000/institutionasset/assetresults/';
const requestUrl = `${href}?fldinstid=3&flddataitem=Data Item:angular/material&sort=${sort}&order=${order}&page=${
page + 1
}`;
return this._httpClient.get<GetAssetApi>(requestUrl);
}
}
html
<div class="example-container mat-elevation-z8">
<div class="example-loading-shade"
*ngIf="isLoadingResults || isRateLimitReached">
<mat-spinner *ngIf="isLoadingResults"></mat-spinner>
<div class="example-rate-limit-reached" *ngIf="isRateLimitReached">
The rate limit has been reached. It will be reset in one minute.
</div>
</div>
<div class="example-table-container">
<table mat-table [dataSource]="data" class="example-table"
matSort matSortActive="client_id" matSortDisableClear matSortDirection="desc">
<!-- Period End Date Column -->
<ng-container matColumnDef="periodenddate">
<th mat-header-cell *matHeaderCellDef>Period End Date</th>
<td mat-cell *matCellDef="let row">{{row.PeriodEndDate | date}}</td>
</ng-container>
<!-- Data Item Value Column -->
<ng-container matColumnDef="dataitemvalue">
<th mat-header-cell *matHeaderCellDef>Data Item Value</th>
<td mat-cell *matCellDef="let row">{{row.DataItemValue}}</td>
</ng-container>
<!-- Data Item Column -->
<ng-container matColumnDef="dataitemname">
<th mat-header-cell *matHeaderCellDef>Data Item Name</th>
<td mat-cell *matCellDef="let row">{{row.DataItemName}}</td>
</ng-container>
<!-- Client id Column -->
<ng-container matColumnDef="client_id">
<th mat-header-cell *matHeaderCellDef mat-sort-header disableClear>
Client id
</th>
<td mat-cell *matCellDef="let row">{{row.Clientid}}</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
</div>
<mat-paginator [length]="resultsLength" [pageSize]="30" aria-label="Select page of Asset"></mat-paginator>
</div>
I get my data from the api and this works.. I get four items in the
array and in console it says object and within the dropdown of objects
in the console it says the field and it's values.
export class InstitutionassetService {
constructor(#InjectDataSource() private dataSource: DataSource) {}
async find(fldinstid: string, flddataitem: string) {
const instassets = await this.dataSource.query(
"dbo.WebGetClientCallSheet #Clientid='" +
fldinstid +
"'," +
"#DataItemName='" +
flddataitem +
"'",
);
return instassets;
}
}
import { Controller, Get, Query } from '#nestjs/common';
import { InstitutionassetService } from './institutionasset.service';
controller from nestjs
#Controller('institutionasset')
export class InstitutionassetController {
constructor(private institutionassetService: InstitutionassetService) {}
#Get('/assetresults')
async find(
#Query('fldinstid') fldinstid: string,
#Query('flddataitem') flddataitem: string,
) {
console.log(fldinstid + ' ' + flddataitem);
return await this.institutionassetService.find(fldinstid, flddataitem);
}
}
I decided to learn angular a few weeks ago, but I have difficulties. I can't populate a table with values received from an API using MatTable .
I am receiving the correct values from the api but these values do not appear in the table, no errors while compiling.
I've tried many solutions but none of them worked. Please help
HTML:
<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 element"> {{element.ID}} </td>
</ng-container>
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef> Name </th>
<td mat-cell *matCellDef="let element"> {{element.name}} </td>
</ng-container>
<ng-container matColumnDef="animaltype">
<th mat-header-cell *matHeaderCellDef> AnimalType </th>
<td mat-cell *matCellDef="let element"> {{element.animaltype}} </td>
</ng-container>
<ng-container matColumnDef="race">
<th mat-header-cell *matHeaderCellDef> Race </th>
<td mat-cell *matCellDef="let element"> {{element.race}} </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
Typescript:
import { AfterViewInit, Component, ViewChild, OnInit } from '#angular/core';
import { MatTableDataSource } from '#angular/material/table';
import { User } from 'src/app/models/user.model';
import { Adoption } from 'src/app/models/adoption.model';
import { AccountService } from '../services/account.service';
#Component({
selector: 'app-myadoptions',
templateUrl: './myadoptions.component.html',
styleUrls: ['./myadoptions.component.css']
})
export class MyadoptionsComponent implements OnInit {
allAdoption: Adoption[];
dataSource: MatTableDataSource<Adoption>;
displayedColumns: string[] = ['ID', 'name', 'animaltype', 'race'];
user: User;
string: string;
payload;
constructor(private accountService: AccountService) {
}
ngOnInit() {
this.adoptions();
}
public adoptions() {
let resp = this.accountService.getAdoptions(this.getUserId());
resp.subscribe(data => {
this.dataSource = new MatTableDataSource(data);
console.log(this.dataSource.data);
});
}
getUserId() {
this.string = localStorage.getItem('user');
this.user = (JSON.parse(this.string));
if (this.user.token) {
this.payload = this.user.token.split(".")[1];
this.payload = window.atob(this.payload);
const userString = JSON.parse(this.payload);
return parseInt(userString.UserID);
}
}
}
Model:
export class Adoption {
id: number;
name: string;
animaltype: string;
race: string;
UserID: number;
text: string;
adopted: boolean;
}
Console log:
Console.log
Table:
table
I suspect that the response from getAdoptions has the data you are looking for in a nested property named data, but what you are loading into the MatTable is the outer response object itself.
i.e., you are doing:
let resp = this.accountService.getAdoptions(this.getUserId());
resp.subscribe(data => {
this.dataSource = new MatTableDataSource(data);
which looks reasonable, but when I look at your console output for this.dataSource.data, I see that the Adoption records are in a property named data. i.e., the original shape of the returned information is probably:
getAdoptionsResponse: {
data: Adoption[];
}
If this is the case, you need to update your code to do:
let resp = this.accountService.getAdoptions(this.getUserId());
resp.subscribe(response => {
this.dataSource = new MatTableDataSource(response.data);
in order to load the data correctly.
You should be able to verify this (or refute it) by printing out the value you get from the getAdoptions subscription.
I am fairly new to Web development and am stuck on this problem from past some days, Would appreciate a heck lot if the community could help me out here
I want to merge two observables coming out of firebase database, I want to join them concurrently i.e
3 rows of the first observable to be mapped with the three rows from the other observable. I want to use this observable into my dataSource for Angular Mat Table. and extract fields from both the observable here
This is the Component.ts
import { Component, OnInit } from '#angular/core';
import { ProductService } from 'src/app/product.service';
import { Observable, observable } from 'rxjs';
import "rxjs/add/observable/zip";
import "rxjs/add/observable/forkJoin";
#Component({
selector: 'app-admin-products',
templateUrl: './admin-products.component.html',
styleUrls: ['./admin-products.component.css']
})
export class AdminProductsComponent implements OnInit {
products$:Observable<any[]>
productsKey$:Observable<any[]>
finalProduct$
list:[]
constructor(private productService:ProductService) {
this.products$ = this.productService.getAll().valueChanges();
this.productsKey$ = this.productService.getAll().snapshotChanges();
//this.finalProduct$ = (this.products$).pipe(merge(this.productsKey$));
}
displayedColumns = ['title','price','edit'];
// dataSource = this.products$
ngOnInit(): void {
}
}
This is the service.ts
import { Injectable } from '#angular/core';
import { AngularFireDatabase } from 'angularfire2/database';
#Injectable({
providedIn: 'root'
})
export class ProductService {
constructor(private db:AngularFireDatabase) { }
create(product){
console.log(product)
return this.db.list('/products').push(product);
}
getAll(){
return this.db.list('/products')
}
}
this is the final HTML markup
<p style="padding: 50px;">
<button mat-flat-button color="primary" routerLink="/admin/products/new" > Add New Product</button>
</p>
<mat-table [dataSource]="finalProduct$ | async" class="mat-elevation-z8">
<!-- Position Column -->
<ng-container matColumnDef="title">
<mat-header-cell *matHeaderCellDef> Title </mat-header-cell>
<mat-cell *matCellDef="let element"> {{ element.title }} </mat-cell>
</ng-container>
<!-- Name Column -->
<ng-container matColumnDef="price">
<mat-header-cell *matHeaderCellDef> Price </mat-header-cell>
<mat-cell *matCellDef="let element"> {{element.price}}</mat-cell>
</ng-container>
<ng-container matColumnDef="edit">
<mat-header-cell *matHeaderCellDef> </mat-header-cell>
<mat-cell *matCellDef="let element"> {{element | json}} </mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
</mat-table>
The first Observable products$ has data in this format
{category: "bread", imageUrl: "https://pixabay.com/photos/bread-food-isolated-croissant-loaf-4592483/", price: 50, title: "Freshly Baked Bread"}
the Second observable productsKey$ has data in this format
{payload: DataSnapshot, type: "value", prevKey: null, key: "-M9HwZl_WYfgTchxanrb"}
I wish to extract the Price, title and key value from these observables and display them in a table.
I would suggest using zip which does exactly what you want, i.e merge 2 observables.
ngOnInit(): void {
zip(this.products$, this.productsKey$).pipe(
map(reponse => { return {...reponse[0], ...response[1]}})
).subscribe(
reponse => {
this.dataSource = reponse;
});
You can also use combineLatest as Michael suggested with slight modifications. Change map(reponse => [...reponse[0], ...response[1]]) to map(reponse => { return {...reponse[0], ...response[1]}})
If the observables are independent of each other you could use RxJS combineLatest() function to combine multiple observables.
displayedColumns = ['title', 'price', 'edit'];
constructor(private productService: ProductService) {
this.products$ = this.productService.getAll().valueChanges();
this.productsKey$ = this.productService.getAll().snapshotChanges();
}
ngOnInit(): void {
combineLatest(this.products$, this.productsKey$).pipe(
take(1), // <-- remove it if the data stream needs to persist
map(reponse => [...reponse[0], ...response[1]])
).subscribe(
reponse => {
this.dataSource = reponse;
}
);
}
I am fetching the data from the server, the data is coming well and showing in the but the paginator is not working although it is only showing.
The paginator is showing the webpage but it is not working as the next button, go to page etc.
<div class="container">
<div class="row">
<div class="col my-3">
<div class="mat-elevation-z8">
<app-message></app-message>
<table mat-table [dataSource]="dataSource">
<!-- Position Column -->
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef> Name </th>
<td mat-cell *matCellDef="let element"> {{element.name}}</td>
</ng-container>
<!-- Position Column -->
<ng-container matColumnDef="phone">
<th mat-header-cell *matHeaderCellDef> Phone </th>
<td mat-cell *matCellDef="let element"> {{element.phone}}</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
<mat-paginator [pageSizeOptions]="[5, 10, 20]" showFirstLastButtons></mat-paginator>
</div>
</div>
</div>
</div>
This is the TS code.
export class UsersComponent implements OnInit {
displayedColumns: string[] = ['name', 'phone'];
dataSource = new MatTableDataSource<PeriodicElement>([]);
#ViewChild(MatPaginator, {static: true}) paginator: MatPaginator;
constructor(public data: DataService, private rest: RestApiService) {}
ngOnInit() {
this.getUsers();
this.dataSource.paginator = this.paginator;
}
async getUsers(){
try {
const data =await this.rest.get("http://localhost:3030/user/auth/all/users");
if(data['status']) {
console.log(data['data']);
this.dataSource = data['data'];
} else {
this.data.error(data['message']);
}
} catch (error) {
this.data.error(error['message']);
}
}
}
interface PeriodicElement {
slno:number,
name: string,
phone: string
}
const dataArray: PeriodicElement[] = [];
Can u integrate AfterViewInit and call this
ngAfterViewInit() {
this.dataSource.paginator = this.paginator;
}
and change
this.dataSource = data['data'];
to
this.dataSource.data = data['data'];
Make sure you import MatPaginator from #angular/material/paginator not #angular/material
Seems like you have not added the corresponding table and paginator modules inside your app.module.ts
app.module.ts
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { FormsModule } from '#angular/forms';
import {MatTableModule} from '#angular/material/table';
import {MatPaginatorModule} from '#angular/material/paginator';
import { AppComponent } from './app.component';
import { HelloComponent } from './hello.component';
#NgModule({
imports: [ BrowserModule, FormsModule, MatTableModule,MatPaginatorModule ],
declarations: [ AppComponent, HelloComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
As your code was not working even on stackblitz, so i have added dummy data to show you an example. Please find stackblitz here: https://stackblitz.com/edit/angular-tcgvnu
HTML file
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
<ng-container matColumnDef="id">
<th mat-header-cell *matHeaderCellDef> No. </th>
<td mat-cell *matCellDef="let element"> {{element.id}} </td>
</ng-container>
<ng-container matColumnDef="stud_id">
<th mat-header-cell *matHeaderCellDef> Stud_id </th>
<td mat-cell *matCellDef="let element"> {{element.stud_id}} </td>
</ng-container>
<ng-container matColumnDef="stud_app_date">
<th mat-header-cell *matHeaderCellDef> Date </th>
<td mat-cell *matCellDef="let element"> {{element.stud_app_date | date}} </td>
</ng-container>
<ng-container matColumnDef="stud_first_name">
<th mat-header-cell *matHeaderCellDef> Name </th>
<td mat-cell *matCellDef="let element"> {{element.stud_first_name}} </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
**component file**
import { Component, OnInit } from '#angular/core';
import { MatTableDataSource } from '#angular/material/table';
import {student} from '../_interface/stud.model';
import { RegistrationService } from '../../../registration.service';
#Component({
selector: 'app-get-stud',
templateUrl: './get-stud.component.html',
styleUrls: ['./get-stud.component.css']
})
export class GetStudComponent implements OnInit {
public displayedColumns = ['id', 'stud_id', 'stud_app_date','stud_first_name'];
public dataSource = new MatTableDataSource<student>();
constructor(private _registrationService : RegistrationService) { }
ngOnInit() : void {
this.getAllStudents();
}
public getAllStudents = () => {
this._registrationService.registerGetStud()
.subscribe(res => {
this.dataSource.data = res as student[],
response => console.log('Success!',response),
error => console.error('Error!',error);
console.log(this.dataSource.data);
})
}
}
**interface**
export interface student{
id: number;
stud_id: string;
stud_app_date: Date;
stud_first_name: string;
}
Unchecked runtime.lastError: The message port closed before a response was received.
I would have to display the mysql table data in angular material table using node js api.. but it is not displaying any data...
Then i checked the node js api using postman and even i checked the console log.. but data's are displaying on both...
Try this by adding change detector to render changes
first, u need to inject it in the constructor
constructor(private readonly changeDetectorRef: ChangeDetectorRef, private _registrationService : RegistrationService)
Then u need to add markforcheck after data added like below
public getAllStudents = () => {
this._registrationService.registerGetStud()
.subscribe(res => {
this.dataSource.data = res as student[]
this.changeDetectorRef.markForCheck();
})
}
component file
public getAllStudents = () => {
this._registrationService.registerGetStud()
.subscribe(res => {
console.log(res),
this.dataSource.data = res.response as student[],
response => console.log('Success!',response),
error => console.error('Error!',error);
console.log(this.dataSource.data);
})
}
Actually, i am sending the result in response(in node js)...so, added the response in component file along with added the data in html file...now its working fine...like
this.dataSource.data = res.response as student[],
{"status":200,"response":[{"id":1,"stud_id":"STUDENT_ID_0",".......
html
<table mat-table [dataSource]="dataSource.data".....
Thank you so much Atresh Kulkarni for your concern