好的,所以我一直在努力解决这个问题。我正在使用名为“Contenful”的服务充当CMS并使用他们的api来获取JSON数据。
我有一个名为'editor.service.ts'的服务如下(我隐藏了'SpaceID'和'访问令牌'以保护隐私):
import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
@Injectable()
export class EditorService {
private baseURL = 'https://cdn.contentful.com';
private spaceID = 'HIDDEN';
private accessToken ='HIDDEN';
private blocksURL = this.baseURL + '/spaces/' + this.spaceID + '/entries?access_token=' + this.accessToken + '&content_type=blocks';
constructor(private http: Http) {}
getBlocks(): Observable<any> {
return this.http.get(this.blocksURL).map((res: Response) => res);
}
}
然后在名为'editor.component.ts'的组件中,我有这个:
import { Component, OnInit } from '@angular/core';
import { EditorService } from './../editor.service';
@Component({
selector: 'app-editor',
templateUrl: './editor.component.html',
styleUrls: ['./editor.component.css'],
providers: [EditorService]
})
export class EditorComponent implements OnInit {
blocksJSON: any;
constructor(private editorService: EditorService) {}
ngOnInit() {
this.editorService.getBlocks().subscribe(res => {
this.blocksJSON = res.json().items;
console.log(this.blocksJSON); //THIS WORKS
});
}
}
这让我感到困惑。该文件中的console.log()行打印出我想要的内容,因此我知道API工作正常。令人困惑的是现在。
在我的模板文件中,我有这一行:
<h1 *ngFor="let block of blocksJSON; let i = index">{{block[i].fields.blockName}}</h1>
在我看来,这应该有效。但是,我一直收到错误
ERROR TypeError: Cannot read property 'fields' of undefined
它打印出这个错误3次,即使此刻,数组'block'中只有1个对象。但我不认为有一个对象是一个问题......(我可能错了)
我不知道为什么会这样,因为console.log打印出我想要的数据,所以我知道应该定义它。我唯一的想法是角度2 HTTP get是异步的,但我真的不知道这是不是问题。
任何建议都将不胜感激。感谢。
答案 0 :(得分:0)
正如我所提到的,主要问题在于:
<?php // demo/temp_elo.php
/**
* Working with substrings
*
* https://stackoverflow.com/questions/45267396/accessing-substrings-in-a-php-array
*/
error_reporting(E_ALL);
echo '<pre>';
$target = "Ninja blah Turtles";
$source = [ "jack and jil", "peter likes pan", "Ninja Turtles" ];
// SEPARATE THE TARGET INTO ITS SUBSTRINGS
$targets = explode(' ', $target);
// TEST EACH OF THE SOURCE STRINGS
foreach ($source as $string)
{
echo PHP_EOL . $string;
foreach ($targets as $tgt)
{
if (stripos($string, $tgt) !== FALSE)
{
echo " CONTAINS $tgt";
}
}
}
如果<h1 *ngFor="let block of blocksJSON; let i = index">{{block[i].fields.blockName}}</h1>
是一个数组,ngFor将负责为你迭代它的元素,这样你就不需要通过它们的索引来访问元素了。
blocksJSON
只要<h1 *ngFor="let block of blocksJSON">{{block.fields.blockName}}</h1>
数组中的每个元素都具有blocksJSON
属性,那就应该有效。
当你刚开始有角度时,我会用这个答案指出你可以改进的其他一些事情:
模型:始终为后端响应定义接口。在地方使用fields
可以避免失败类型脚本的最大目的之一:强类型。
例如,定义以下内容:
any
<强>服务强>
export interface BlockFields{
blockName: string;
// more properties
}
export interface Block{
fields: BlockFields;
.... //more properties
}
<强>组件:强>
import { Response, Http} from '@angular/http';
import { Block } from '...' // the place where you saved the response interface
import { _throw } from 'rxjs/observable/throw';
import { ErrorObservable } from 'rxjs/observable/ErrorObservable';
@Injectable()
export class EditorService {
private baseURL = 'https://cdn.contentful.com';
private spaceID = 'HIDDEN';
private accessToken ='HIDDEN';
private _blocksUrl = `${this.baseUrl}/spaces/${this.spaceID}/entries?access_token=${this.accessToken}&content_type=blocks`; //template strings makes concatenation of multiple static sections and parameters cleaner
constructor(private http: Http) {}
getBlocks(): Observable<Block[]> {
return this.http.get(this.blocksURL)
.map(this.extractData)
.catch(this.handleError); // always handle your http errors at service level first.
}
private extractData(response: Response){
return response.json();
}
private handleError(error: any): ErrorObservable {
let errMsg: string;
if (error instanceof Response) {
const body = error.json() || '';
const err = JSON.stringify(body);
errMsg = `${error.status} - ${error.statusText || ''} Details: ${err}`;
} else {
errMsg = error.message ? error.message : error.toString();
}
return _throw(errMsg);
};
}