0

When I am calling the following function to get data from MongoDB, I am getting an undefined. I suspect it is because I need to convert the function to an async/await function. However, I am not sure how to do this without breaking the functions and their chains as they stand? Is there a simple way to convert this to async/await?

studentRoute.route('/read-student/:id').get((req, res) => {
   
    Student.findById(req.params.id, (error, data) => {
      if (error) {
        return next(error)  
      } else {
        res.json(data)
      }
    })
})

At my angular front end I have the following service:

  // Get student
  GetStudent(id): Observable<any> {
    let API_URL = `${this.endpoint}/read-student/${id}`;
    return this.http.get(API_URL, { headers: this.headers })
      .pipe(
        map((res: Response) => {
          return res || {}
        }),
        catchError(this.errorMgmt)
      )
  }

In my angular component ts file I have contract.component.ts:

import { Component, ViewChild, OnInit } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';  // this is needed to get the params from the routes
import { ApiService } from './../../shared/api.service';
import { Student } from './../../shared/student';
import { Web3Service } from './../../shared/web3.service';
import { MatPaginator } from '@angular/material/paginator';
import { MatTableDataSource } from '@angular/material/table';


@Component({
  selector: 'app-contract',
  templateUrl: './contract.component.html',
  styleUrls: ['./contract.component.css']
})
export class ContractComponent implements OnInit {
  StudentData: any = [];
  dataSource: MatTableDataSource<Student>;
  @ViewChild(MatPaginator) paginator: MatPaginator;
  displayedColumns: string[] = [
                                 'a',
                                 'b', 
                                 'c', 
                                 'd',
                                 'e',
                                 'f',
                                 'g',
                                 'h',
                                 'i',
                                 'j',
                                 'k',
                                 'l'   
                               ];

  constructor(

    private router: Router,
    private actRoute: ActivatedRoute,
    private studentApi: ApiService

  ) { 
   
      var id = this.actRoute.snapshot.paramMap.get('id');
      this.studentApi.GetStudent(id).subscribe(data => {
        this.StudentData = data;
        this.dataSource = new MatTableDataSource<Student>(this.StudentData);
        setTimeout(() => {
          this.dataSource.paginator = this.paginator;
        }, 0);
      })

  }

  ngOnInit(): void {
  }


}



The corresponding contract.component.html file gives the undefined error for data coming from mongdb if I use findbyid()

I am starting from the following tutorial for reference: https://www.positronx.io/angular-8-mean-stack-tutorial-build-crud-angular-material/

Zakoff
  • 12,665
  • 5
  • 22
  • 35
  • What is `undefined`, the response at client? `data`? – Rashomon Oct 07 '20 at 20:04
  • @Rashomon the res.json(data) returns the value. I am using the tutorial at https://www.positronx.io/angular-8-mean-stack-tutorial-build-crud-angular-material/. A similar function to get all students works successfully with only the res.json(data). I have reduced the problem to needing to convert this to await/async. Full code is in the tutorial. – Zakoff Oct 07 '20 at 20:09
  • Why not console.log the error message to ascertain what is really throwing the error. This is because mongoose can also work using the callback approach you used. – chyke007 Oct 08 '20 at 13:56

1 Answers1

0

It turned out the issue was the same as this. When one item is returned by the database, it is an object and not an array. The object has an undefined length

Typescript Convert Object to Array - because *ngFor does not supports iteration of object

Zakoff
  • 12,665
  • 5
  • 22
  • 35