-1

Desire

I'm attempting to pull data from MongoDB and display it in an Angular Material Table.

Issue

While I am able to see the results of my MongoDB call when logging to the console/terminal, the Chrome browser console tells me that my JSON data has been stored into 'window.json' and I don't know how to reference that within my application. If I hard code some test JSON data into my application and reference that instead of trying to call from MongoDB, then the data populates in my Angular Material Table without issue.

Configuration

I have an Express/Node application that is making the calls to MongoDB and providing the data via http calls. I have a separate Angular application that is attempting to make an http call to the Express/Node application to consume the JSON from MongoDB and display it in the Material Table. All applications and MongoDB are running local on my computer (Windows 10). Versions of packages:

  • Node 9.3.0
  • TypeScript 2.6.2
  • Express 4.16.2
  • MongoDB Node Driver 2.2.33
  • Angular 5.x

Sample MongoDB Data in the Movies Collection

{
        "_id" : ObjectId("56918f5e24de1e0ce2dfccc3"),
        "title" : "Once Upon a Time in the West",
        "year" : 1968,
        "imdb" : "tt0064116",
        "type" : "movie"
}
{
        "_id" : ObjectId("56918f5e24de1e0ce2dfccc4"),
        "title" : "A Million Ways to Die in the West",
        "year" : 2014,
        "imdb" : "tt2557490",
        "type" : "movie"
}
{
        "_id" : ObjectId("56918f5e24de1e0ce2dfccc5"),
        "title" : "Wild Wild West",
        "year" : 1999,
        "imdb" : "tt0120891",
        "type" : "movie"
}
{
        "_id" : ObjectId("56918f5e24de1e0ce2dfccc6"),
        "title" : "West Side Story",
        "year" : 1961,
        "imdb" : "tt0055614",
        "type" : "movie"
}
{
        "_id" : ObjectId("56918f5e24de1e0ce2dfccc7"),
        "title" : "Slow West",
        "year" : 2015,
        "imdb" : "tt3205376",
        "type" : "movie"
}

Angular Application (Front End)

Note that the Angular application was created using the Angular CLI.

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { MatTableModule } from '@angular/material/table';
import { MatPaginatorModule } from '@angular/material';
import { HttpClientModule } from '@angular/common/http';

import { AppComponent } from './app.component';
import { TestService } from './services/test.service';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    MatTableModule,
    MatPaginatorModule,
    HttpClientModule
  ],
  providers: [TestService],
  bootstrap: [AppComponent]
})
export class AppModule { }

test.service.ts

The "serviceUrl" path provides an array of data from MongoDB by using the following code in the back end Express application:

let movieResults = await db.collection("movies").find().toArray();

return movieResults;

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import { Movie } from '../models/movie.model';

@Injectable()
export class TestService {

  private serviceUrl = 'http://localhost:3000/moviesdb';

  constructor(private http: HttpClient) {}

  getTest(): Observable<Movie[]> {
    return this.http.get<Movie[]>(this.serviceUrl);
  }
}

movie.model.ts

export interface Movie {
  title: string;
  year: number;
  imdb: string;
  type: string;
}

app.component.ts

import { Component, OnInit, ViewChild } from '@angular/core';
import { MatPaginator, MatTableDataSource } from '@angular/material';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';
import { DataSource } from '@angular/cdk/collections';
import { Movie } from './models/movie.model';
import { TestService } from './services/test.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  title = 'My App';
  displayedColumns = ['title', 'year', 'imdb', 'type'];
  
  movies: Movie[];
  dataSource = new TestDataSource(this._testService);

  constructor(private _testService: TestService) {}
  
  ngOnInit(){}
}

export class TestDataSource extends DataSource<any> {
  constructor(private _testService: TestService) {
    super();
  }

  connect(): Observable<Movie[]> {
    return this._testService.getTest();
  }
  disconnect() {}
}

app.component.html

<div style="text-align:center">
  <h1 id="title">
    Welcome to {{ title }}!
  </h1>
</div>

<div class="example-container mat-elevation-z8">
  <h2>Here are some movies you may be interested in:</h2>
  <mat-table #table [dataSource]="dataSource">

    <!-- Title Column -->
    <ng-container matColumnDef="title">
      <mat-header-cell *matHeaderCellDef> Title </mat-header-cell>
      <mat-cell *matCellDef="let movie"> {{movie.title}} </mat-cell>
    </ng-container>

    <!-- Year Column -->
    <ng-container matColumnDef="year">
      <mat-header-cell *matHeaderCellDef> Year </mat-header-cell>
      <mat-cell *matCellDef="let movie"> {{movie.year}} </mat-cell>
    </ng-container>

    <!-- IMDB Column -->
    <ng-container matColumnDef="imdb">
      <mat-header-cell *matHeaderCellDef> IMDB </mat-header-cell>
      <mat-cell *matCellDef="let movie"> {{movie.imdb}} </mat-cell>
    </ng-container>

    <!-- Type Column -->
    <ng-container matColumnDef="type">
      <mat-header-cell *matHeaderCellDef> Type </mat-header-cell>
      <mat-cell *matCellDef="let movie"> {{movie.type}} </mat-cell>
    </ng-container>

    <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
    <mat-row *matRowDef="let row; columns: displayedColumns"></mat-row>
  </mat-table>
</div>

Articles Referenced

Many thanks in advance for any guidance that you can provide!

4
  • You may want to look at the various posts in Stack Overflow regarding Mat Table and Firebase. Commented Jan 5, 2018 at 17:10
  • 2
    Try to produce a minimum code so that user will read your question, I dont think this long question will be read by anyone. Commented Jan 5, 2018 at 17:10
  • Thanks for the recommendation @AniruddhaDas. I'll reformat the question for the minimum code. I was trying to be as thorough as possible before to ensure that follow-up questions would not be required. Can someone tell me if posting a public repository on Github would be a preferred method for longer examples, or is it best to simply keep everything contained within the Stack Overflow post? Commented Jan 7, 2018 at 20:23
  • Yes. I think GitHub link will be fine Commented Jan 7, 2018 at 21:52

1 Answer 1

1

Material table component use "dataSource" variable so you need to use "datasource" in service response with OnInit.

An Example:

ngOnInit() {
this._humanService.getHumans().subscribe(
  resp => {
    this.dataSource  = new MatTableDataSource(resp);
  }, err => {
    console.log(err);
  });

}

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.