[英]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.