简体   繁体   English

Angular2无法映射单个JSON对象?

[英]Angular2 unable to map a single JSON object?

How do you map and use a JSON reponse that is a single object, rather than an array? 如何映射和使用单个对象而不是数组的JSON响应?

Recently, I started adding a new feature to a project I'm working on that should be taking a JSON response from an API and filling out a simple template with data from it. 最近,我开始向正在处理的项目中添加一项新功能,该功能应该是从API接收JSON响应,然后使用其中的数据填写一个简单的模板。 Shouldn't be difficult, right? 不难,对吧? Well, no... and yet, yes... 好吧,不...但是,是...

Mock version of the JSON response: JSON响应的模拟版本:

{
    "id": 1,
    "name": "Acaeris",
}

profile.service.ts profile.service.ts

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

/**
 * This class provides the Profile service with methods to read profile data
 */
@Injectable()
export class ProfileService {
    /**
     * Creates a new ProfileService with the injected Http.
     * @param {Http} http - The injected Http.
     * @constructor
     */
    constructor(private http: Http) {}

    /**
     * Returns an Observable for the HTTP GET request for the JSON resource.
     * @return {Profile} The Observable for the HTTP request.
     */
    get(): Observable<Profile> {
        return this.http.get('assets/profile.json')
            .map(res => <Profile>res.json())
            .catch(this.handleError);
    }

    /**
     * Handle HTTP error
     */
    private handleError (error: any) {
        let errMsg = (error.message) ? error.message :
            error.status ? `${error.status} - ${error.statusText}` : 'Server error';
        console.error(errMsg);
        return Observable.throw(errMsg);
    }
}

profile.component.ts profile.component.ts

import { Component, OnInit } from '@angular/core';
import { ProfileService } from '../services/profile/profile.service';
import { Profile } from '../services/profile/profile';

/**
 * This class represents the lazy loaded ProfileComponent
 */
@Component({
    moduleId: module.id,
    selector: 'sd-profile',
    templateUrl: 'profile.component.html',
    styleUrls: ['profile.component.css'],
})
export class ProfileComponent implements OnInit {

    errorMessage: string;
    profile: Profile;

    /**
     * Creates an instance of the ProfileComponent with the injected
     * ProfileService
     *
     * @param {ProfileService} profileService - The injected ProfileService
     */
    constructor(public profileService: ProfileService) {}

    /**
     * Get the profile data
     */
    ngOnInit() {
        this.getProfile();
    }

    /**
     * Handles the profileService observable
     */
    getProfile() {
        this.profileService.get()
            .subscribe(
                data => this.profile = data,
                error => this.errorMessage = <any>error
            );
    }
}

profile.ts profile.ts

export interface Profile {
    id: number;
    name: string;
}

And I'm just trying to output it using {{profile.name}} but this ends up with the console showing a whole load of error messages and no output. 而且我只是想使用{{profile.name}}输出它,但这最终会在控制台上显示全部错误消息且没有输出。 If I try to check the contents of profile after it has loaded, it tells me it is undefined . 如果在加载profile后尝试检查其内容,它会告诉我它是undefined

However, here's the confusing part. 但是,这是令人困惑的部分。 If I replace all the Profile references to Profile[] , wrap the JSON in an array, add *ngFor="let p of profile" abd use {{p.name}} everything works fine. 如果我替换所有对Profile[]Profile引用,则将JSON包装在一个数组中,然后添加*ngFor="let p of profile" abd use {{p.name}}一切正常。 Unfortunately, in the actual finished application I would not have control of the JSON format. 不幸的是,在实际完成的应用程序中,我无法控制JSON格式。 So what am I doing wrong when trying to handle it as a single object in comparison to handling as an array of objects? 那么,与将其作为对象数组进行处理相比,尝试将其作为单个对象进行处理时我做错了什么?

Looks like at expression {{profile.name}} profile variable is undefined at page rendering moment. 看起来表达式{{profile.name}}的配置文件变量在页面呈现时未定义。 You can try either add some getter like this: 您可以尝试添加一些吸气剂,如下所示:

get profileName(): string { return this.profile ? this.profile.name ? ''; }

and use at template {{profileName}} or you can use ngIf at template like this: 并在模板{{profileName}}上使用,也可以在模板上使用ngIf,如下所示:

<div *ngIf="profile">{{profile.name}}</div>

or shorter (as drewmoore suggested at comment below): 或更短(如drewmoore在以下评论中建议的那样):

<div>{{profile?.name}}</div>

When you are working with array it is the same situation - at first rendering time array is undefined. 使用数组时,情况相同-最初渲染时数组未定义。 ngFor handles this for you and renders nothing. ngFor为您处理此问题,不呈现任何内容。 When async operation of getting 'profile items' is complete - UI is rerendered again with correct values. 完成获取“配置文件项”的异步操作后-会再次以正确的值重新呈现UI。

The map function returns Observables which are a collection of elements. map函数返回Observables,它是元素的集合。 It basically work the same way as the map function for arrays. 它的工作原理基本上与数组的map函数相同。

Now to solve you can replace the Profile references by Profile[] and use {{profile[0].name}} . 现在要解决,可以将Profile引用替换为Profile Profile[]并使用{{profile[0].name}}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM