0
votes

I'm Having issues building a dynamic data-table using mat-table.

I've built it pretty close to the example on the Angular Docs.

Here is my .ts file:

import { Component, OnInit } from '@angular/core';
import { ApiService } from '../../../../core/services/api.service';
import { Course } from '../../../../core/models/course.model';

enum courseType {
  onDemand = 1,
  live = 0,
}

enum sort {
  upcoming = 0,
  title = 1
}

@Component({
  selector: 'app-courses',
  templateUrl: './courses.component.html',
  styleUrls: ['./courses.component.scss']
})
export class CoursesComponent implements OnInit {
  page = 1;
  sort = sort.upcoming;
  type = courseType.live;
  filters: CourseFilters;

  displayedColumns: string[] = ['Name', 'Start Date', 'End Date', 'Authors', 'Active', 'Event Id', 'TMS Id'];

  dataSource: Course[];

  constructor(private api: ApiService) { }

  ngOnInit() {
    this.getCourses();
  }

  onTabChange(e) {
    if (e.tab.textLabel === 'Live') {
      this.type = courseType.live;
    } else {
      this.type = courseType.onDemand;
    }

    this.getCourses();
  }

  getCourses() {
    this.filters = {
      authors: [],
      tags: [],
      title: '',
      tmsId: ''
    };

    this.api.getCourses(this.filters, this.page, '', this.sort, this.type, true, 10).subscribe(response => {
      this.dataSource = response.result;
      console.log(this.dataSource);
    });
  }
}

And my html:

<mat-card class="container">

  <mat-tab-group (selectedTabChange)="onTabChange($event)">
    <mat-tab label="Live"></mat-tab>
    <mat-tab label="On Demand"></mat-tab>
  </mat-tab-group>

  <mat-card-content *ngIf="dataSource">
    <table mat-table [dataSource]="dataSource">

      <ng-container [matColumnDef]="column" *ngFor="let column of displayedColumns">
        <th mat-header-cell *matHeaderCellDef>{{ column }}</th>
        <td mat-cell *matCellDef="let element"> {{ element[column] }} </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>

Courses Model looks like:

export interface Course {
  name: string;
  startDate: Date;
  endDate: Date;
  authors: string[];
  active: boolean;
  id: number;
  trainingSystemId1: string;
}

A typical course obj looks like:

active: true
authors: (3) ["...", "...", "..."]
endDate: "2019-08-29T16:00:00"
id: 1111
name: "..."
startDate: "2019-08-29T15:00:00"
trainingSystemId1: "11111"

The api service method, getCourses(), returns a list of courses from a server.

ApiService:

import { Injectable } from '@angular/core';
import { HttpClient, HttpParams } from '@angular/common/http';
import { environment } from '../../../environments/environment';
import { ApiResponse } from '../models/api-response.model';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class ApiService {

  constructor(private http: HttpClient) { }

  // Courses
  // tslint:disable-next-line: max-line-length
  getCourses(filters: any, page: number, search: string, sort: number, type: number, detailed: boolean, limit?: number,): Observable<ApiResponse> {
    const coursesFilter = {
      type,
      page,
      sort,
      filters,
      search,
      limit,
      detailed,
    };

    return this.http.post<any>(`${environment.apiUrl}courses`, coursesFilter);
  }

  getCourse(id: number): Observable<ApiResponse> {
    return this.http.get<ApiResponse>(`${environment.apiUrl}course/${id}`);
  }
}

I keep getting the "Provided data source did not match an array, Observable, or DataSource" error. Any ideas what I'm doing wrong?

1
where did you get the error ? I believe it's in the service, what is the shape of your ApiService ? - Crocsx
I added my ApiService but I do not believe its happening in the service. - Cobblestonie
there is a typo also on getCourses etailed: boolean, limit?: number,): Observable<ApiResponse> the , after number. - Crocsx
Fixed but That has no effect on the result because typescript. - Cobblestonie
OK, so I made a really dumb error when setting the response.result to the dataSource. So I fixed it and no errors however the datatable is now empty. - Cobblestonie

1 Answers

0
votes

You only add #table <table mat-table [dataSource]="dataSource" #table> in html file after you add @ViewChild('table') table: MatTable<any>; in you ts and when you assign the data in dataSource variable, you put this.table.renderRows(); sentence

this.dataSource = data;
this.table.renderRows();