I am experimenting with the Angular Material table component. For some reason, it does not render any data in the component giving me an error:
Could not find column with id "id".
I can't understand this - there is a row in my data with the column id
.
My in-memory data service provider looks like this:
import { Injectable } from '@angular/core';
import { InMemoryDbService, RequestInfo } from 'angular-in-memory-web-api'
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class Contact {
id!: string;
name!: string;
email!: string;
}
export class BackendService implements InMemoryDbService {
constructor() { }
createDb(reqInfo?: RequestInfo | undefined): {} | Observable<{}> | Promise<{}> {
let contacts = [
{ id: 1, name: 'Contact 1', email: 'contact1@email.com' },
{ id: 2, name: 'Contact 2', email: 'contact2@email.com' },
{ id: 3, name: 'Contact 3', email: 'contact3@email.com' },
{ id: 4, name: 'Contact 4', email: 'contact4@email.com' }
];
return { contacts };
}
}
My component looks like this:
import { Component, OnInit, ViewChild } from '@angular/core';
import { ContactService } from '../contact.service';
import { firstValueFrom } from 'rxjs';
import { Contact } from '../backend.service';
import { MatTableDataSource } from '@angular/material/table';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
const COLUMNS_SCHEMA = [
{
key: "id",
type: "text",
label: "Id"
},
{
key: "name",
type: "text",
label: "Name"
},
{
key: "email",
type: "text",
label: "E-mail"
},
]
@Component({
selector: 'app-contact-list',
templateUrl: './contact-list.component.html',
styleUrl: './contact-list.component.css'
})
export class ContactListComponent implements OnInit {
@ViewChild('paginator') paginator!: MatPaginator;
@ViewChild(MatSort) sort!: MatSort;
dataSource!: MatTableDataSource<Contact>;
displayedColumns: string[] = COLUMNS_SCHEMA.map((col) => col.key);
columnsSchema: any = COLUMNS_SCHEMA;
contacts: any[] = [];
constructor(private contactService: ContactService) {
}
async ngOnInit(): Promise<void> {
const data: any = await firstValueFrom(this.contactService.getContacts());
console.log(data);
this.contacts = data;
this.dataSource = new MatTableDataSource(this.contacts);
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
console.log(this.displayedColumns);
}
}
and lastly my template looks like this:
<mat-table class="lessons-table mat-elevation-z8" [dataSource]="dataSource">
<ng-container matColumnDef="date">
<mat-header-cell *matHeaderCellDef mat-sort-header> Id </mat-header-cell>
<mat-cell *matCellDef="let contact">
<input type="text" matInput [value]="contact.id" readonly>
</mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns"></mat-row>
</mat-table>
The error mentions that there is no column definition for "id" in your <mat-table>
. You must define all the columns as provided in the displayColumns
array. Otherwise, remove the element that is unneeded from the displayColumns
array.
Reference Define the column templates.
<mat-table class="lessons-table mat-elevation-z8" [dataSource]="dataSource">
<ng-container matColumnDef="id">
<mat-header-cell *matHeaderCellDef mat-sort-header> Id </mat-header-cell>
<mat-cell *matCellDef="let contact">
<input type="text" matInput [value]="contact.id" readonly />
{{ contact.id }}
</mat-cell>
</ng-container>
<ng-container matColumnDef="name">
<mat-header-cell *matHeaderCellDef mat-sort-header> Name </mat-header-cell>
<mat-cell *matCellDef="let contact">
<input type="text" matInput [value]="contact.name" readonly />
{{ contact.name }}
</mat-cell>
</ng-container>
<ng-container matColumnDef="email">
<mat-header-cell *matHeaderCellDef mat-sort-header> Email </mat-header-cell>
<mat-cell *matCellDef="let contact">
<input type="text" matInput [value]="contact.email" readonly />
{{ contact.email }}
</mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns"></mat-row>
</mat-table>