我正在开发角度应用程序,我需要应用以下机制:
我的视图有2个部分(项目列表和详细信息,如果选择项目)。用户可以单击某个项目,下一个服务将获取该项目的其他数据并在详细视图中显示它们。此外,如果可用,我想在开始时自动选择第一项。
这是我的服务:
@Injectable()
export class ItemService {
private url: string;
private itemSource = new BehaviorSubject<Item>(null);
selectedItem = this.itemSource.asObservable();
constructor(private http: HttpClient) {
this.url = 'http://localhost:8080/api/item';
}
getItems(): Observable<Item[]> {
let observable = this.http.get<Item[]>(this.url)
.map(items => items.map(item => {
return new Item(item);
}));
return observable;
}
selectItem(item: Item) {
return this.http.get<Item>(this.url + '/' + item.id)
.map(item => new Item(item))
.subscribe(t => this.itemSource.next(t));
}
}
详细信息组件我订阅了这样的选项:
ngOnInit() {
this.itemService.selectedItem.subscribe(item => this.selectedItem = item);
}
以下代码来自我的组件,其中我显示了项目列表。我还希望在订阅数据后设置所选项目,但我的代码不起作用。我在html模板中迭代items []属性并显示数据,但是当我订阅数据后访问此数组时,我得到了未定义。你能修好我的代码吗?谢谢!
public items = [];
constructor(private itemService: ItemService) { }
ngOnInit() {
this.itemService.getItems()
.subscribe(
data => this.items = data,
err => console.log(err),
function () {
console.log('selected data', this.items); // this prints undefined
if (this.items && this.items.length) {
this.itemService.selectedItem(this.items[0])
}
});
}
答案 0 :(得分:3)
您的问题是,在complete
的通话中,您没有使用箭头功能进行subscribe
回调。如您所见,您正在使用next
和error
的箭头函数。
使用function(...) {...}
定义新功能时,您正在创建新的上下文,因此this
关键字会更改其含义。箭头函数和普通函数之间的区别(除了在我看来更优雅),箭头函数没有为this
定义新的上下文,因此该关键字的含义与上下文中的相同他们是定义的。因此,在您的next
和error
回调中,this
是您的组件,但在致电complete
时,this
最可靠的是, window
,其中没有items
属性,因此为undefined
。
将您的代码更改为:
public items = [];
constructor(private itemService: ItemService) { }
ngOnInit() {
this.itemService.getItems()
.subscribe(
data => this.items = data,
err => console.log(err),
() => {
console.log('selected data', this.items); // this prints undefined
if (this.items && this.items.length) {
this.itemService.selectedItem(this.items[0])
}
});
}
我想您在那里使用了function
关键字,因为该函数没有参数,但您可以使用语法() => expression
或() => {...}
data => this.items = data
是一种更简单,更优雅的写作方式
(data) => { return this.items = data; }