[英]Share and update Observable data in Angular 2
I have 2 components - object-list
and search-filter
in my app. 我的应用程序包含2个组件- object-list
和search-filter
。 Also I have a fetch-service
with getObjects(page, filter)
method. 我也有一个带getObjects(page, filter)
方法的fetch-service
。 I want to implement a scenario where object-list
fetches all data via getObjects
method and then search-filter
will apply some filters to getObjects
and object-list
should automatically update. 我想实现一个方案,其中object-list
通过getObjects
方法获取所有数据,然后search-filter
将一些过滤器应用于getObjects
并且object-list
应自动更新。 Here is some code: 这是一些代码:
FetchService FetchService
objects: Observable<any>;
getObjects(page: number, filter): void {
let headers = new Headers();
headers.append('Content-Type', 'application/json');
const offset = (page - 1)* this.pageSize;
let url = this.objectsBaseUrl;
//apply filter
if (filter) {
url = `${url}?filter=${JSON.stringify(filter)}`
}
this.objects = this.http.get(url)
.map((response: Response) => {
return response.json() || {}
})
.catch(this.handleError);
}
ObjectListComponent ObjectListComponent
constructor(private fetch: FetchService) {}
ngOnInit(): void {
this.fetch.getObjects(this.initialPage);
this.objects = this.fetch.objects; // I need an Observable object to use with async pipe with *ngFor
}
getPage(page: number) {
this.fetch.getObjects(page); //here this.objects variable probably should be update because this methods replaces this.fetch.objects
}
SearchFilter SearchFilter
constructor(private fetch: FetchService) {}
apply() {
//some filter calculations
this.fetch.getObjects(1, this.filter);
}
I don't use subscribe
to objects
because I put it to async pipe in *ngFor
. 我不使用subscribe
objects
因为我将其放入*ngFor
异步管道。 But as far as I'm concerned async pipe uses subscribe
inside. 但是就我而言,异步管道使用内部subscribe
。 The problem is that the list updates only once when ngOnInit
fires. 问题在于,当ngOnInit
触发时,列表仅更新一次。 What's going wrong? 怎么了
The SearchFilter
component should NOT be in charge of fetching the data. SearchFilter
组件不应负责获取数据。
Here's how I would do it: 这是我的处理方式:
1) Create 3 components 1)创建3个组件
FetchService
. 一个父组件 ,也称为“智能组件”,用于处理侦听过滤器更改和使用FetchService
提取数据的所有逻辑。 The parent component has two children displayed in its template: 父组件的模板中显示了两个子组件: SearchFilterComponent
is a "dumb component" (or presentational component). 第一个孩子: SearchFilterComponent
是一个“哑组件”(或表示组件)。 Its only job is to emit an @Output
event every time the filters change, passing the latest filter values to its parent. 它唯一的工作是每次过滤器更改时都发出一个@Output
事件,将最新的过滤器值传递给其父级。 ObjectListComponent
is also a "dumb component". 第二个子对象: ObjectListComponent
也是一个“哑组件”。 Its only job is to display the list of objects provided by its parent component via an @Input
property. 它的唯一工作是通过@Input
属性显示其父组件提供的对象列表。 2) Implement the following workflow 2)实施以下工作流程
SearchFilterComponent
, emit an @Output
event passing the latest filter values, eg this.filtersChanged.emit(filters)
. 当过滤器在SearchFilterComponent
更改时,发出一个@Output
事件,传递最新的过滤器值,例如this.filtersChanged.emit(filters)
。 <search-filter (filtersChanged)="getObjects($event)">
. 在父组件中,使用<search-filter (filtersChanged)="getObjects($event)">
监听过滤器更改。 The getObjects(filters)
method will re-fetch the objects on every filter change; getObjects(filters)
方法将在每次过滤器更改时重新获取对象; it should store the fetched objects in a property of the parent component, let's call it results
. 它应该将获取的对象存储在父组件的属性中,我们称其为results
。 results
to its child component ObjectListComponent
via an @Input property called objects
: <object-list [objects]="results">
. 然后,父组件通过称为objects
的@Input属性将results
传递给子组件ObjectListComponent
: <object-list [objects]="results">
。 The object list should refresh automatically every time the input changes. 每次输入更改时,对象列表应自动刷新。 Hopefully my explanations will make sense. 希望我的解释会有意义。 Read up on @Input and @Output on the angular.io site if you're not familiar with those. 如果您不熟悉@@ Input和@Output,请在angular.io网站上阅读。 I don't have time to create a Plunkr, so please post questions if anythings seems unclear. 我没有时间创建Plunkr,所以如果有什么不清楚的地方,请发表问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.