I'm trying to display some data in angular material data-table,my service class method has data but its not displaying in data-table, please help me ,am unable to find mistake in data-table from last 3 hours
service class and api
getfriendAnswers(id: number): Observable<FriendDetails[]> {
debugger;
return this.httpClient.get<FriendDetails[]>(this.apiUrl + '/Questions/yourFriendAnswerdCount/' + id)
}
[HttpGet, Route("yourFriendAnswerdCount/{id}")]
public ActionResult getFriendAnswerdCount(int id)
{
return Ok(userRepository.getFriendAnswerdCount(id));
}
friend details class
export interface FriendDetails {
Id: number;
UserId: number;
AnsweredCount: number;
FriendName: string;
}
component class
export class FriendAnswredComponent implements OnInit {
id;
constructor(private service: UserService,private route: ActivatedRoute) { }
dataSource :FriendDetails[]=[];
displayedColumns: string[] = [ 'FriendName', 'AnsweredCount',];
ngOnInit() {
this.id = parseInt(this.route.snapshot.paramMap.get('id'));
this.service.getfriendAnswers(this.id).subscribe(b => {
debugger;
this.dataSource = b;
});
}
}
material data-table template
<mat-card>
<mat-card-title>your friends answered count questions are</mat-card-title>
<mat-card-content>
<div *ngIf="dataSource">
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
<!--- Note that these columns can be defined in any order.
The actual rendered columns are set as a property on the row definition" -->
<!-- Name Column -->
<ng-container matColumnDef="FriendName">
<th mat-header-cell *matHeaderCellDef> FriendName </th>
<td mat-cell *matCellDef="let element"> {{element.FriendName}} </td>
</ng-container>
<!-- Weight Column -->
<ng-container matColumnDef="AnsweredCount">
<th mat-header-cell *matHeaderCellDef> AnsweredCount </th>
<td mat-cell *matCellDef="let element"> {{element.AnsweredCount}} </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
</div>
</mat-card-content>
</mat-card>
{{dataSource[0]?.AnsweredCount}}
service returns this output
{id: 5, userId: 11, answeredCount: 2, friendName: "sarala"}
I'm getting empty data table even service returns data
you are trying to bind dataSource[0]?.AnsweredCount when AnsweredCount does not exist in your object.
It should be answeredCount, not AnsweredCount:
{{dataSource[0]?.answeredCount}}
Related
I am trying to create a dialog box with a table inside of it. I already created it but then I was told to use mat-table instead of creating a table from scratch and ever since that, I have been stuck with this particular error. I'll share my code to make it more convenient. These are the files I have.
asm-prop.interface.ts
export interface Properties {
name: string;
value: number;
}
asm-prop.component.ts
import { Component, ViewChild } from '#angular/core';
import { ContextMenuComponent } from 'ngx-contextmenu';
import { MatDialogRef } from '#angular/material/dialog';
import { AssemblyFetchService } from 'src/app/assembly/assembly-fetch.service';
import { Properties } from './asm-prop.interface';
#Component({
selector: 'asm-prop',
templateUrl: 'asm-prop.component.html',
styleUrls: ['asm-prop.component.scss'],
providers: []
})
export class AsmPropComponent {
#ViewChild(ContextMenuComponent) public customContextMenu: ContextMenuComponent;
asmProps = null;
displayedColumns: string[] = ['Property Name', 'Value'];
storedProperties: Properties[];
public constructor(public asmPropDialogRef: MatDialogRef<AsmPropComponent>, public asmFetchServ: AssemblyFetchService) {
this.storedProperties = [
{ name: 'Number of Assemblies:', value: this.asmFetchServ.propertiesDialogComponentStatistics.propertiesDialogComponentStatistics.assembly_statistics.num_assemblies },
{ name: 'Number of Assembly Instances:', value: this.asmFetchServ.propertiesDialogComponentStatistics.assembly_statistics.num_assembly_instances },
{ name: 'Number of Part Instances:', value: this.asmFetchServ.propertiesDialogComponentStatistics.assembly_statistics.num_assembly_instances },
{ name: 'Number of Parts:', value: this.asmFetchServ.propertiesDialogComponentStatistics.assembly_statistics.num_parts },
{ name: 'Number of Contact Instances', value: this.asmFetchServ.propertiesDialogComponentStatistics.assembly_statistics.num_contacts },
{ name: 'Number of Contacts:', value: this.asmFetchServ.propertiesDialogComponentStatistics.assembly_statistics.num_contacts },
{ name: 'Nesting Level:', value: this.asmFetchServ.propertiesDialogComponentStatistics.assembly_statistics.nesting_level },
];
}
closeDialog(): void {
this.asmPropDialogRef.close();
}
}
asm-prop.component.html
<h1 mat-dialog-title> Properties of {{asmFetchServ.propertiesDialogComponentName}}</h1>
<div>
<table mat-table #table [dataSource]="storedProperties" class="mat-elevation-z8">
<!-- Position Column -->
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef> Property Name </th>
<td mat-cell *matCellDef="let element"> {{element.name}} </td>
</ng-container>
<!-- Name Column -->
<ng-container matColumnDef="value">
<th mat-header-cell *matHeaderCellDef> Value </th>
<td mat-cell *matCellDef="let element"> {{element.value}} </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef=" displayedColumns">
</tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
<div mat-dialog-actions>
<button mat-button (click)="closeDialog()">Close</button>
</div>
For all of your information, I have already included MatTableModule in app.module.ts. What is the correct way to go about it?
I have a reusable table the [cellData]="row" populate each cell on the table (sample table is on the screenshot).
What I want is how to we replace the null values on the template with "---" so that instead of displaying nothing on the cell if value is empty I wanna display "---".
Is it possible to do it in <app-table-multi-sort-cell-default [cellData]="row" [id]="column.id" [subId]="getColumnSubId(column.id)" [columnName]="column.name"></app-table-multi-sort-cell-default> so I don't have to modify the row objects and just do it in the template. Thanks for any help.
#table-multi-sort.component.html code
<ng-container *ngFor="let column of table.columns" [matColumnDef]="column.id">
<mat-header-cell class="table-multi-sort-header" *matHeaderCellDef [mat-multi-sort-header]="column.id">
<div>{{column.name}}</div>
<div class="sub-text">{{getColumnSubtitle(column.id)}}</div>
</mat-header-cell>
<mat-cell *matCellDef="let row" (click)="editRow(row)">
<ng-container *ngIf="column.id !== 'action'; then col; else actionCol"></ng-container>
<ng-template #col>
<app-table-multi-sort-cell-default [cellData]="row" [id]="column.id" [subId]="getColumnSubId(column.id)" [columnName]="column.name"></app-table-multi-sort-cell-default>
</ng-template>
<ng-template #actionCol>
<app-table-multi-sort-cell-action [rowData]="row" [actions]="getActions(column.id)" (actionClickEvent)="clickTableAction($event,row)"></app-table-multi-sort-cell-action>
</ng-template>
</mat-cell>
</ng-container>
enter image description here
#table-multi-sort-cell-default.component.html
<div>{{cellData[id]}}</div>
<div class="cellSubText secondary-text">{{cellData[subId]}}</div>
#table-multi-sort-cell-default.component.ts
export class TableMultiSortCellDefaultComponent implements OnInit {
#Input() cellData:any;
#Input() id: any;
#Input() subId:any;
#Input() columnName: any;
constructor() { }
ngOnInit(): void {
}
}
You can create a simple function for handling null values:
export class TableMultiSortCellDefaultComponent implements OnInit {
#Input() cellData:any;
#Input() id: any;
#Input() subId:any;
#Input() columnName: any;
constructor() { }
ngOnInit(): void {
}
public customFunc(row: any, columnId: any) {
row[columnId] = row[columnId] == null ? '---' : row[columnId];
return row;
}
}
And in the template:
<app-table-multi-sort-cell-default
[cellData]="customFunc(row, column.id)"
[id]="column.id"
[subId]="getColumnSubId(column.id)"
[columnName]="column.name">
</app-table-multi-sort-cell-default>
I have an angular PWA with a material table with data from firebase, the data is showned and the paginator is working but I also want to sort its data, but mat-sort doesn't work. It shows the arrow to sort the data, but when clicking the arrow the data is not sorted.
I have followed the documentation from Angular Material.
The table in the component template:
<ng-container matColumnDef="movimento">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Tipo de movimento</th>
<td mat-cell *matCellDef="let movimento"> {{movimento.mapValue.fields.tipo_movimento.stringValue}}
</td>
</ng-container>
<ng-container matColumnDef="valor">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Valor</th>
<td mat-cell *matCellDef="let movimento">
{{movimento.mapValue.fields.valor.doubleValue | number:'1.1-2'}}
{{movimento.mapValue.fields.valor.integerValue}} €
</td>
</ng-container>
<ng-container matColumnDef="data">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Data</th>
<td mat-cell *matCellDef="let movimento"> {{movimento.mapValue.fields.data.timestampValue | date}}
</td>
</ng-container>
<ng-container matColumnDef="desc">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Descrição</th>
<td mat-cell *matCellDef="let movimento"> {{movimento.mapValue.fields.desc.stringValue}}</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
<mat-paginator [pageSizeOptions]="[10, 20, 40]" showFirstLastButtons></mat-paginator>
The Component:
#Component({
selector: 'app-movimentar',
templateUrl: './visualizar-movimentos.component.html',
styleUrls: ['./visualizar-movimentos.component.css']
})
export class VisualizarMovimentosComponent implements OnInit {
user: firebase.User;
userData;
displayedColumns: string[] = ['movimento', 'valor', 'data', 'desc'];
dataSource = new MatTableDataSource<Movimentos>();
#ViewChild(MatPaginator, { static: false })
set paginator(value: MatPaginator) {
this.dataSource.paginator = value;
}
#ViewChild(MatSort, { static: false }) sort: MatSort;
constructor(private auth: AuthService,
private router: Router,
private afs: AngularFirestore) { }
ngOnInit() {
this.auth.getUserState()
.subscribe(user => {
this.user = user;
this.getUserData();
});
}
/* loadLessonsPage() {
this.dataSource._orderData;
debugger
} */
getUserData(): void {
this.auth.getUserData(this.user.uid)
.subscribe(user => {
this.userData = user;
this.dataSource = new MatTableDataSource(this.userData._document.proto.fields.movimentos.arrayValue.values);
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
});
}
login() {
this.router.navigate(['login']);
}
logout() {
this.auth.logout();
this.router.navigate(['inicio']);
}
register() {
this.router.navigate(['/register']);
}
trackByUid(index, item) {
return item.uid;
}
}```
Thanks for the help in advance.
The problem was with the data from firebase, it was not compatible with the mat sort. To solve it you need a map like this one:
Here's the map
return data.reduce((acc, value) => {
return [
...acc,
Object.entries(value.mapValue.fields).reduce((accValue, [key, value]) => {
return {
...accValue,
[key]: Object.values(value)[0]
}
}, {})
]
}, [])
}
you need to specify mat sort in your table like this and on the columns on which you want to sort the data.
<table matSort (matSortChange)="sortData($event)">
</table>
for sort on column
<th mat-header-cell *matHeaderCellDef mat-sort-header>
On your .ts file
#ViewChild(MatSort, { static: false }) set content(content: ElementRef) {
this.sort = content;
if (this.sort) {
this.dataSource.sort = this.sort;
}
}
And you have already done this part when you load data
getUserData(): void {
this.auth.getUserData(this.user.uid)
.subscribe(user => {
this.userData = user;
this.dataSource = new MatTableDataSource(this.userData._document.proto.fields.movimentos.arrayValue.values);
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
});
}
It should work now!
We know it is easy to do sorting and pagination in angular(only consider sorting in client end). refer to : https://stackblitz.com/angular/dnblbyvggqyj?file=src%2Fapp%2Ftable-sorting-example.ts.
But how to integrate sorting and pagination for several seperate tables(same data structure for these tables).
For my understanding, in order to do this, we need serveral viewChild(the number of viewchild equals to the number of table). Also we need to initialize serveral MatTableDataSource objects. We can put it in a hashmap Like:
{table1Tittle: new MatTableDataSource<Object>(), table2Tittle: new MatTableDataSource<Object>(), ...., };
But the thing is we don't know the number of table before we get the data. How should we decorate the viewchild and let the number of viewchild to be same as the number of table.
{'k1' : [{'id' : '1'}, {'id': '2'} ], 'k2': [{}]}
convert the object above to array and assign to tables and loop tables like below, Ignore if it is already an array.
you can do something like this in component1
<div *ngFor="let t of tables">
// app-table is the selector of component2
<app-table [tablename]="t.k1" [tablesource]="t1.tableArray" > </app-table>
</div>
in component2.ts write something like this
import {MatPaginator} from '#angular/material/paginator';
copy below line below to your class constructor
#ViewChild(MatPaginator) paginator: MatPaginator;
#Input() tablename: string;
#Input() tablesource: any;
copy below line in your function
this.dataSource = new MatTableDataSource(this.tablesource);
this.dataSource.paginator = this.paginator;
create component2.html and write code like below
<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 = "id2">
<th mat-header-cell *matHeaderCellDef> id2</th>
<td mat-cell *matCellDef = "let element"> {{element.id2}} </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef = "displayedColumns"></tr>
<tr mat-row *matRowDef = "let row; columns: displayedColumns;"></tr>
</table>
<mat-paginator [pageSizeOptions]="[20, 30, 50]" showFirstLastButtons></mat-paginator>
I would use mat-table in my project
In my component file I use observable to catch data from DB and print them in my data table.
I tried to follow the official tutorial but nothing is printed on screen and I don't get error
export class ListeProjetsComponent implements OnInit {
constructor(private ajoutProj: AjoutprojService) { }
nouveauProjet: NouveauProjet[];
ngOnInit(){
this.getAllProj();
}
displayedColumns = ['name'];
dataSource = new MatTableDataSource<NouveauProjet>(this.nouveauProjet);
applyFilter(filterValue: string) {
filterValue = filterValue.trim(); // Remove whitespace
filterValue = filterValue.toLowerCase(); // MatTableDataSource defaults to lowercase matches
this.dataSource.filter = filterValue;
}
getAllProj() {
this.ajoutProj.getAllProj().subscribe(
response => {
this.nouveauProjet = response; console.log(this.nouveauProjet) // data is printed in the browser console. but not on screen
},
error => console.log(error)
);
}
}
Html file
<div class="example-container mat-elevation-z8">
<div class="example-header">
<mat-form-field>
<input matInput (keyup)="applyFilter($event.target.value)" placeholder="Filter">
</mat-form-field>
</div>
<mat-table #table [dataSource]="dataSource">
<ng-container matColumnDef="name">
<mat-header-cell *matHeaderCellDef> Name </mat-header-cell>
<mat-cell *matCellDef="let element"> {{element.nomProj}} </mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
</mat-table>
</div>
This might be happening because you initialize the table with an empty data set:
dataSource = new MatTableDataSource<NouveauProjet>(this.nouveauProjet);
At this point, this.nouveauProjet presumably does not contain any data;
Try re initializing the table data source when you get the data from your service:
getAllProj() {
this.ajoutProj.getAllProj().subscribe(
response => {
// set dataSource here
this.dataSource = new MatTableDataSource<NouveauProjet>(response);
},
error => console.log(error)
);
}