Pedro Lopes
Pedro Lopes

Reputation: 481

Angular2 Map "Cannot read property 'map' of undefined"

So i just started learning Angular2 and im trying to get the data i have on my database and display it on my indexpage but everytime i try to do so i get an error saying "Cannot read property 'map' of undefined" and i have no idea why i have been searching for hours. Can someone please help me out.

import { Component } from '@angular/core';
import { Http, Response, Headers } from '@angular/http';
import { Observable } from 'rxjs/Rx';
import { Injectable } from '@angular/core';
import { Bootcamp } from './Bootcamp';

const BOOTCAMP: Bootcamp[] = [];

@Injectable()

export class Bootcamptest {
    private baseUrl: string = 'http://localhost:54220/Bootcampdata';

    constructor(private http: Http) { }

    getAll(): Observable<Bootcamp[]> {
        let bootcamp$ = this.http
            .get(`${this.baseUrl}/GetAlleBootcamps`, { headers: this.getHeaders() })
            .map(mapBootcamps)
            .catch(handleError);

        return bootcamp$;
    }

    private getHeaders() {
        let headers = new Headers();
        headers.append('Accept', 'application/json');  
        return headers;
    }
}

function mapBootcamps(response: Response): Bootcamp[] {
    // uncomment to simulate error:
    // throw new Error('ups! Force choke!');

    // The response of the API has a results
    // property with the actual results

    return response.json().results.map(toBootcamp)
} 

function toBootcamp(r: any): Bootcamp {
    let bootcamp = <Bootcamp>({
        id: extractId(r),
        naam: r.name,
        description: r.description,
        begindatum: r.begindatum,
        einddatum: r.einddatum
    });

    console.log('Parsed bootcamp:', bootcamp);
    return bootcamp;
}

// to avoid breaking the rest of our app
// I extract the id from the person url
function extractId(bootcampData: any) {
    let extractedId = bootcampData.url.replace('http://localhost:54220/Bootcampdata/Getallebootcamps', '').replace('/', '');
    return parseInt(extractedId);
}

function mapBootcamp(response: Response): Bootcamp {
    // toBootcamp looks just like in the previous example
    return toBootcamp(response.json());
}

// this could also be a private method of the component class
function handleError(error: any) {
    // log error
    // could be something more sofisticated
    let errorMsg = error.message || `Error met het laden van data!`
    console.error(errorMsg);

    // throw an application level error
    return Observable.throw(errorMsg);
}

The component class

import { Component, OnInit } from '@angular/core';
import { Bootcamp } from './Bootcamp';
import { Bootcamptest } from './Bootcamptest';

@Component({
    selector: 'my-bootcamptest',
    template: `
  <section>
    <section *ngIf="isLoading && !errorMessage">
    Loading our hyperdrives!!! Retrieving data...
    </section>
      <ul>
        <!-- this is the new syntax for ng-repeat -->
        <li *ngFor="let person of people">
            <a>
          {{bootcamp.naam}}
          </a>
        </li>
      </ul>
      <section *ngIf="errorMessage">
        {{errorMessage}}
      </section>
  </section>
  `
})
export class Bootcamplistcomponent implements OnInit {
    bootcamp: Bootcamp[] = [];
    errorMessage: string = '';
    isLoading: boolean = true;

    constructor(private bootcamptest: Bootcamptest) { }

    ngOnInit() {
        this.bootcamptest
            .getAll()
            .subscribe(
         /* happy path */ p => this.bootcamp = p,
         /* error path */ e => this.errorMessage = e,
         /* onComplete */() => this.isLoading = false);
    }
}

Upvotes: 2

Views: 14022

Answers (2)

Nirvan Nagar
Nirvan Nagar

Reputation: 369

I know this is old but I just ran into this issue myself. I'm assuming you were also using the following tutorial:

https://www.barbarianmeetscoding.com/blog/2016/04/02/getting-started-with-angular-2-step-by-step-6-consuming-real-data-with-http/

I was stuck for a long time until I started to dissect my equivalent of "mapBootcamps". What I found was that the ".results" part of the following line: "return response.json().results.map(toBootcamp)" was returning a value of undefined. Thus, when the ".map(toBootcamp)" method is called, it throws the error "Cannot read property 'map' of undefined".

To fix the problem, I simply removed ".results" from the line "return response.json().results.map(toBootcamp)" and it worked!

Hope that helps!

Upvotes: 4

Supamiu
Supamiu

Reputation: 8731

Your problem seems to be coming from your API.

In the mapBootcamps you commented that every API response had a results property but it seems like sometimes it doesn't.

Your console.log showed that you had an array of object, so results does not exist, it is null.

If you change response.json().results.map(toBootcamp) to response.json()[0].results.map(toBootcamp) it'll work, but I don't think that's what you have to do, you should create a method to handle data as an array, or change the return format of your API to an object.

Upvotes: 1

Related Questions