0

Ich versuche, eine Benutzerdetailseite zu erstellen, auf der Sie weitere Informationen zum ausgewählten Benutzer erhalten. Wenn Sie auf einen Benutzernamen aus der Liste klicken, navigiert es auf die Seite Benutzerdaten erfolgreich wirft aber diesen Fehler:Angular 2 - Navigieren zur Benutzerdetailseite zeigt keine ausgewählten Benutzerdetails

Unhandled Promise rejection: Error in src/person-details.component.html:3:25 caused by: Cannot read property 'id' of undefined

Hier ist ein zupfen: http://embed.plnkr.co/cUEIag77etv95ZFJY3iN/

und hier sind die Codes :

Person-list.component.ts

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

import { IPerson } from './person'; 
import { AppService } from './app.service'; 

@Component({ 
    selector: 'my-list', 
    templateUrl: 'src/person-list.component.html' 
}) 

export class PersonListComponent implements OnInit { 

    _persons: IPerson[]; 
    selectedPerson: IPerson; 

    constructor(
    private _appService: AppService, 
    private router: Router) { } 

    ngOnInit(): void { 
    this._appService.getPersons() 
     .subscribe(
     _persons => this._persons = _persons); // set our local _persons array equal to the IPerson[] data which arrive from our data stream 
    } 

    goToDetails(person: IPerson): void { 
    this.router.navigate(['/user', person.id]) 
    } 
} 

Person-list.component.html

<div class="container-fluid"> 
    <div class='table-responsive'> 
    <table class='table'> 
     <thead> 
     <tr> 
      <th>Id</th> 
      <th>Name</th> 
     </tr> 
     </thead> 

     <tbody> 
     <tr *ngFor="let person of _persons" (click)="goToDetails(person)" class="row"> 
      <td>{{person.id}}</td> 
      <td>{{person.name}}</td> 
     </tr> 
     </tbody> 
    </table> 
    </div> 
</div> 

Person-details.component.ts

import { Component, OnInit } from '@angular/core'; 
import { ActivatedRoute, Params } from '@angular/router'; 
import { Location } from '@angular/common'; 

import { AppService } from './app.service'; 
import { IPerson } from './person'; 

@Component({ 
    selector: 'my-details', 
    templateUrl: 'src/person-details.component.html' 
}) 

export class PersonDetailsComponent implements OnInit { 

    constructor(
    private _appService: AppService, 
    private route: ActivatedRoute, 
    private location: Location 
) { } 

    ngOnInit(): void { 
    this.route.params.forEach((params: Params) => { // delivers our array of route parameters. 
     let id = +params['id']; // The person id is a number. Route parameters are always strings. So we convert the route parameter value to a number with the JavaScript (+) operator. 
     this._appService.getPerson(id) 
     .map(person => this.person = person); 
    }); 
    } 

    // navigates backward one step in the browser's history stack using the Location service we injected 
    goBack(): void { 
    this.location.back(); 
    } 
} 

Person-details.component.html

<div class="container"> 
    <h3>Person Details</h3> 
    <div class="col-md-12"> 
    <div><span>Id:</span> {{person.id}}</div> 
    <div><span>Name:</span> {{person.name}}</div> 
    <div><span>Description:</span> {{person.description}}</div> 
    </div> 
    <button (click)="goBack()">Back</button> 
</div> 

app.service.ts

import { Injectable } from '@angular/core'; 
import { Http, Response } from '@angular/http'; // required for getting persons from JSON file 
import { Observable } from 'rxjs/Observable'; 
import 'rxjs/add/operator/map'; // required by the .map method 

import { IPerson } from './person'; 

@Injectable() export class AppService { 

    private _personUrl = 'src/persons.json'; 

    constructor(private _http: Http) { } // required to Inject Http as a dependency. Creates a private _http variable and assigns the injected service instance to that variable 

    getPersons(): Observable<IPerson[]> { 
     return this._http.get(this._personUrl) 
      .map((response: Response) => <IPerson[]>response.json().personData); // we let the compiler know that the array contains items of type 'IPerson' and return the 'personData' object from the json file as an array 
    } 

    // filters the person list from getPersons by id 
    getPerson(id: number): Observable<IPerson> { 
     return this.getPersons() 
      .map(persons => persons.find(person => person.id === id)); 
    } 
} 

Antwort

2

Wenn die PersonDetailsComponen t ist initialisiert das Feld person ist null und das verursacht einen Fehler in den Template-Bindings. Sie können die Vorlagenbindungen durch field?.subfield ersetzen.

<div class="container"> 
    <h3>Person Details</h3> 
    <div class="col-md-12"> 
    <div><span>Id:</span> {{person?.id}}</div> 
    <div><span>Name:</span> {{person?.name}}</div> 
    <div><span>Description:</span> {{person?.description}}</div> 
    </div> 
    <button (click)="goBack()">Back</button> 
</div> 

I edited Ihre plunker auf eine Version mit diesen Änderungen. Ich musste auch die PersonDetailsComponent bearbeiten, um die getPerson() Observable zu abonnieren.

+0

danke für die schnelle antwort. Der Elvis-Operator löst das Problem nur in der Konsole. Was ich versuche zu erreichen, ist, die ausgewählten Benutzerinformationen anzuzeigen, aber die Eigenschaft "person" ist aus irgendeinem Grund undefiniert. – Todor

+0

Gerade die Antwort bearbeitet. Ich hoffe es hilft. –

+0

Ok, ich hab's! Ich habe vergessen, das Observable zu abonnieren. Übrigens sind die elvis-Betreiber nicht verpflichtet, dies zum Funktionieren zu bringen. Danke noch einmal! – Todor

Verwandte Themen