【发布时间】:2018-05-20 15:47:56
【问题描述】:
回到学习 Angular 并扩展英雄之旅教程。我有一个将数据加载到 BehaviorSubject 的共享数据服务。问题是当我尝试使用 *ngFor 迭代数据时,我得到“找不到不同的支持对象”错误。从所有其他问题中,我知道它正在尝试绑定到一个对象而不是一个数组,但是对于我的生活,我无法弄清楚为什么。或者需要将什么对象转换为数组。
我正在使用 Angular 5.0.5。有趣的是,这适用于 Angular 4,但显然我在升级中破坏了一些东西。
对我做错了什么有什么想法吗?除了一切。 :D 哈哈
这是我的服务
import { Injectable, EventEmitter } from '@angular/core';
import { HttpHeaders, HttpClient } from '@angular/common/http';
import { Subject } from 'rxjs/Subject';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Observable } from 'rxjs/Observable';
import { Hero } from '../models/hero';
@Injectable()
export class HeroService {
private heroesUrl = 'api/heroes';
private headers = new HttpHeaders({'Content-Type': 'application/json'});
private loadingSubject = new BehaviorSubject<boolean>(false);
private dataSubject = new BehaviorSubject<Hero[]>([]);
private http: HttpClient;
constructor(http: HttpClient) {
this.http = http;
}
public getLoadingStream(): Observable<boolean> {
return this.loadingSubject.asObservable();
}
public getDataStream(): Observable<Hero[]> {
return this.dataSubject.asObservable();
}
public load(): void {
this.loadingSubject.next(true);
this.http.get<Hero[]>(this.heroesUrl).subscribe(data => {
this.dataSubject.next(data);
this.loadingSubject.next(false);
});
}
public search(term: string): void {
this.loadingSubject.next(true);
this.http
.get<Hero[]>(`${this.heroesUrl}/?name=${term}`)
.subscribe(data => {
this.dataSubject.next(data);
this.loadingSubject.next(false);
});
}
}
列表组件
import { Component, OnInit, OnDestroy, Input, Output, EventEmitter } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { Subscription } from 'rxjs/Subscription';
import { HeroService } from '../../services/hero.service';
import { Hero } from '../../models/hero';
@Component({
selector: 'hero-list',
templateUrl: './hero-list.component.html',
styleUrls: ['./hero-list.component.css']
})
export class HeroListComponent implements OnInit {
private dataSubscription: Subscription;
private loadingSubscription: Subscription;
private heroService: HeroService;
heroes: Hero[] = [];
isLoading: boolean;
@Output()
public onHeroSelected = new EventEmitter<Hero>();
constructor(heroService: HeroService) {
this.heroService = heroService;
}
ngOnInit() {
this.loadingSubscription = this.heroService.getLoadingStream()
.subscribe(loading => {
this.isLoading = loading;
});
this.dataSubscription = this.heroService.getDataStream()
.subscribe(data => {
this.heroes = data;
});
}
ngOnDestory() {
this.dataSubscription.unsubscribe();
this.loadingSubscription.unsubscribe();
}
onSelect(hero: Hero) {
this.onHeroSelected.emit(hero);
}
}
列表模板
<div *ngIf="isLoading">Loading ...</div>
<div *ngIf="!isLoading" class="ui relaxed divided list">
<div *ngFor="let hero of heroes" class="item" (click)="onSelect(hero)">
<span class="ui blue circular label">{{ hero.id }}</span>
<div class="content">
<a class="header">{{ hero.name }}</a>
<div class="description">...</div>
</div>
</div>
</div>
【问题讨论】:
-
看起来非常快,我认为这是因为您的服务是异步的,因此当您的数据
isLoading为 false 时,它会尝试显示并遍历您的数组。但是在那一刻,您的数组没有设置,因为它是异步的。尝试从*ngIf=!isLoading更新到*ngIf=!isLoading && heroes > 0 -
将
this.dataSubject.next(data);替换为console.log(data); this.dataSubject.next(data);。控制台记录了什么?真的是数组吗? -
@JBNizet 是的,数据是一个包含 10 个元素的数组。
-
证明它。发布在控制台中记录的结果。如果更容易复制和粘贴,请使用
console.log(JSON.stringify(data))。 -
@JBNizet {"data":[{"id":11,"name":"蝙蝠侠"},{"id":12,"name":"超人"},{" id":13,"name":"蜘蛛侠"},{"id":14,"name":"雷神"},{"id":15,"name":"金刚狼"},{"id" :16,"name":"神奇女侠"},{"id":17,"name":"美国队长"},{"id":18,"name":"钢铁侠"},{"id ":19,"name":"绿巨人"},{"id":20,"name":"Duke"}]}