我正在寻找相当于做这样的事情但是对于一个Observable而不是一个常规数组:
var i = this.customers.findIndex(customer => customer._id === id); ~i && this.customers[i] = newObject.
我在屏幕上有2个组件.左侧的列表组件和右侧的显示组件(想象它是一个只呈现最新’版本’数据的PDF)
单击列表中的项目时,它会在右侧的组件中显示该选定项目的数据.
该列表是一个可观察的数组:
items$: Observable<Proposal[]>;
列表中的每个项目都有一个子组件.可以单击单个项目上的图标,这会更改该子项的数据.孩子有一个事件发射器告诉父母数据已经改变:
@Output() proposalDataChanged: EventEmitter<string> = new EventEmitter();
父母绑定它:
<fb-proposal-list-item [proposal]="proposal" (proposalDataChanged)="handleDataChanged(p)"> </fb-proposal-list-item>
我遇到的问题是在handleDataChanged方法中,我想在Observable中搜索已更改的项,并将其替换为从发射器返回的新有效负载.我不想调用服务器来刷新整个列表.
我需要这样做,以便右侧的组件反映新数据.
我能找到这样的项目:
handleDataChanged(data: Proposal){ this.items$.subscribe((items: Proposal[]) => item = items.find(p => p.id == data.id)); }
但无法弄清楚如何更新Observable中的项目,而不仅仅是找到更改的项目.
我知道我可以通过在其他地方导航然后再返回以强制刷新来“欺骗”组件,但这也会触及API(并重新加载页面).
网址如下所示:
/pages/proposals/manage/-XHzOJY/document
url中的slug是当前所选项目的id(在右侧的组件中呈现).
所以我不能在这里使用params更改检测,因为它不会改变.用户正在对已选择的对象进行更改,该对象是可观察数组内的许多对象之一.
UPDATE
以下是父组件的完整代码:
import { Component,OnInit } from '@angular/core'; import { Router } from '@angular/router'; import { Observable,Subject } from 'rxjs/Rx'; import { Proposal } from '../proposal'; import { ProposalService } from '../proposal.service'; import { SearchService } from '../../services/search-service'; @Component({ selector: 'fb-proposal-list',templateUrl: './proposal-list.component.html',styleUrls: ['./proposal-list.component.css'] }) export class ProposalListComponent implements OnInit { total$: Observable<number>; items$: Observable<Proposal[]>; term: string = ""; currentPage: number = 1; private pageStream = new Subject<number>(); constructor( private _searchService: SearchService,private _proposalService: ProposalService,private _router: Router) { } ngOnInit() { this.setupSearching(); // let timer = Observable.timer(0,60000); // timer.subscribe(() => this.goToPage(this.currentPage)); } setupSearching(){ const searchSource = this._searchService.searchTermStream .map(searchTerm => { this.term = searchTerm; return {search: searchTerm,page: 1} }); const pageSource = this.pageStream.map(pageNumber => { this.currentPage = pageNumber; return {search: this.term,page: pageNumber} }); const source = pageSource .merge(searchSource) .startWith({search: this.term,page: this.currentPage}) .switchMap((params: {search: string,page: number}) => { return this._proposalService.getProposalsPaged(params.search,params.page) }) .share(); this.total$= source.pluck('Meta').pluck('total_items'); this.items$= source.pluck('items'); } goToPage(page: number) { this.pageStream.next(page) } handleDataChanged(id: string){ this.goToPage(this.currentPage); } }
实际上,它是一系列发射的集合.因此,当你有Observable< Model []>时,它不是某个观察者正在观察的集合,它实际上是一个发出的Model []集合的流.从这个意义上说,你不能更新发射的值(显然,因为它已经被发射),但你想要的是observable发出另一个更新的Model集合.
在你尝试之前,你必须知道你不能从你自己没有创造的可观察物中发出一些东西.你需要的是一个Subject,一个Observable和Observer的对象(它继承了Observer和Observable接口).
那么,让我们构建类似的东西:
subject: Subject<Proposal[]> = new Subject(); _proposals: Proposal[] = []; get proposals() { return this.subject.asObservable(); }
假设您通过某些API调用获得了提案:
http.get("...").map(response => response.json().subscribe(data => { this._proposals= <Proposal[]>data; // save your data this.subject.next(this._proposals); // emit your data });
现在,您想要更新您的数据:
updateProposals() { this._proposals = this._proposals.filter(...); // or whatever this.subject.next(Object.assign({},this._proposals)); // emit completely new value }
这可能看起来很多,我建议您阅读更多有关Observables如何为您未来可能遇到的问题而工作的内容.干杯.