Reputation: 597
I am an Angular2 newbie. When I try to add this code into camp.detail.component.html (for detail/:id API view),
{{campDetail.campground.name}}
it always appears the following error message:
When I remove
{{campDetail.campground.name}}
then there is no error message, and we can see the object is printed in the console:
I did many searches and tried as many solutions as possible but still find no proper way to solve this problem. (e.g: Angular 2 router Error: Uncaught (in promise): TypeError: Cannot read property 'resolve' of undefined , Uncaught (in promise): Error: Cannot read property of undefined , Angular 2 Uncaught (in promise): TypeError: Cannot read property 'isActivated' of undefined , https://github.com/angular/angular/issues/8519 )
How do I solve this exception? Any suggestion will be helpful and useful for me. I really appreciate it.
My files are below:
campgrounds.service.ts
import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';
import 'rxjs/add/operator/toPromise';
import { Campground } from "../models/campground";
import { Comment } from "../models/comment";
export class CampDetail {
campground: Campground;
comments: Comment[];
}
@Injectable()
export class CampgroundService {
private campgroundsUrl = 'api/campground';
constructor(private http: Http) { }
getCamps(): Promise<Campground[]> {
return this.http.get(this.campgroundsUrl)
.toPromise()
.then(response => response.json())
.catch(this.handleError);
}
getCamp(id: number): Promise<CampDetail> {
return this.http.get(this.campgroundsUrl + '/' + id)
.toPromise()
.then(response => response.json())
.catch(this.handleError);
}
private handleError(error: any): Promise<any> {
console.error('An error occurred', error);
return Promise.reject(error.message || error);
}
}
campground.ts
export class Campground {
id: number;
name: string;
image: string;
description: string;
username: string;
user_id: number;
}
comment.ts
export class Comment {
id: number;
text: string;
campground_id: number;
username: string;
user_id: number;
}
camp.detail.component.ts
import 'rxjs/add/operator/switchMap';
import { Component, Input, OnInit } from '@angular/core';
import { ActivatedRoute, Params } from '@angular/router';
import { CampgroundService, CampDetail } from "../../services/campgounds.service";
@Component({
selector: 'campDetail',
templateUrl: './app/components/campgrounds/camp.detail.component.html'
})
export class CampDetailComponent implements OnInit {
error: any;
campDetail: CampDetail = new CampDetail();
constructor(
private campgroundService: CampgroundService,
private route: ActivatedRoute) {
}
ngOnInit() {
this.route.params
.switchMap((params: Params) => this.campgroundService.getCamp(params['id']))
.subscribe(data => {
this.campDetail = data;
console.log(this.campDetail);
});
}
}
campground.component.ts
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { CampgroundService } from "../../services/campgounds.service";
import { Campground } from "../../models/campground";
@Component({
selector: 'camps',
templateUrl: './app/components/campgrounds/campgrounds.component.html',
styleUrls: ['./app/components/campgrounds/campgrounds.component.css']
})
export class CampgroundsComponent implements OnInit {
camps: Campground[];
constructor(private router: Router, private campService: CampgroundService) { }
getCamps() {
this.campService.getCamps().then(camps => this.camps = camps);
}
ngOnInit() {
this.getCamps();
}
gotoDetail(id: number) {
this.router.navigate(['/detail', id]);
}
}
The weird thing is when I call the campground API using getCamps() in campground.component, everything works properly. After clicking the button
<button class="btn btn-primary" (click)="gotoDetail(camp.id)"> More Info </button>
and directing to another page, I will get this error.
Upvotes: 0
Views: 2145
Reputation: 13058
Since your campDetail
data is loaded asynchronously, and isn't available at the time the component is created, you need to check its nested properties' path using the Angular safe navigation operator:
{{campDetail?.campground?.name}}
Upvotes: 4