0

I'm slowly building an angular2 site, but I'm very inexperienced with this platform still. Right now I have two components that use the same service: stories and storyDetails. The stories component just gets a list of all stories from my web api. The storyDetails component will list more detailed information about a single story. The stories component works fine, but I am getting an error when I try to load the storyDetails component.

Uncaught (in promise): Error: Error in /app/stories/details/storyDetails.component.template.html:0:22 caused by: Cannot read property 'title' of undefined

I've breakpointed on my service's extractData function and verified that json is being returned and has the following value: body = Object {storyId: 1, urlAffix: "a_story_title", title: "A Story Title", text: "This is the story", entityId: null…} However, it should be noted that I'm getting the error before this line is ever executed.

Here are the relevant files:

storyService.service.ts

import {Injectable} from '@angular/core';
import {Story} from '../story';
import { Http, Response } from '@angular/http';
import { Observable }     from 'rxjs/Observable';

@Injectable()
export class StoryService {
    private storyUrl = 'http://localhost:51332/api/storyapi';  // URL to web API
    constructor(private http: Http) { }
    getStories(): Observable<Story[]> {
        return this.http.get(this.storyUrl)
            .map(this.extractData)
            .catch(this.handleError);
    }
    getStoryDetails(storyId: Number): Observable<Story> {
        return this.http.get(`${this.storyUrl}/${storyId}`)
            .map(this.extractData)
            .catch(this.handleError);
    }
    private extractData(res: Response) {
        let body = res.json();
        return body;
    }
    private handleError(error: any) {
        let errMsg = (error.message) ? error.message :
            error.status ? `${error.status} - ${error.statusText}` : 'Server error';
        console.error(errMsg); // log to console instead
        return Observable.throw(errMsg);
    }
}

storyDetails.component.ts

import { Component } from '@angular/core';
import { OnInit } from '@angular/core';

import { Story } from '../story.ts';
import { StoryService } from '../services/storyService.service';

import { ActivatedRoute } from '@angular/router';

@Component({
    selector: 'storyDetails',
    templateUrl: '/app/stories/details/storyDetails.component.template.html',
    providers: [StoryService]
})

export class StoryDetails implements OnInit {
    errorMessage: string;
    story: Story;
    mode = 'Observable';
    storyId: Number;
    private sub: any;
    constructor(private storyService: StoryService, private route: ActivatedRoute) { }
    ngOnInit() {

        this.route.params.subscribe(params => {
            this.storyId = +params['id']; // (+) converts string 'id' to a number
            this.getStoryDetails(this.storyId);
        });
    }
    getStoryDetails(storyId : Number) {
        this.storyService.getStoryDetails(storyId)
            .subscribe(
            story => this.story = story,
            error => this.errorMessage = <any>error);
    }
    ngOnDestroy() {
        this.sub.unsubscribe();


  }
}

storyDetails.component.template.html

<h2>Story Details</h2>


{{story.title}}

story.ts

export class Story {
    public storyId: Number;
    public urlAffix: string
    public title: string;
}

I noticed that if I don't put anything in the template html file that references the story object, I don't get the error. I'm sure I'm making a rookie mistake but I just cannot find it.

1 Answer 1

1

The storyDetails component is trying to render {{story.title}} before it is defined. Try wrapping your component or just the title in an *ngIf. Once the asynchronous call is complete (and story is defined) the span will render along with the title.

<span *ngIf="story">
    {{story.title}}
</span>
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.