Reputation: 2114
I'm trying to follow the "Observable data store" pattern in Angular 2 (detailed in this blog post from Angular University) From what I understand, this means that, if I have a service called TodoStore,
I would subscribe to TodoStore.items$
so I could get all the latest updates for my to-do list in real time (as other components add, remove, or edit Todos
.
However, what if I have two components side-by-side that display different Todo
lists, filtered on the server-side? One might display Todo
s due today while another would show Todo
s due on a user-selected date.
In this case, I would not be able to use the same TodoStore
, as both would be fetching different data from the server. How do I handle sharing this service between these two components? My urge is to go back to an angular1-style getToDoList()
service method, but then I'm storing state inside a single component and can't possibly share data between multiple components without making extra API calls.
Upvotes: 1
Views: 1528
Reputation: 16892
If your lists really have to be filtered server-side and you have an unknown number of simultaneously displayed lists and a new server-request has to me made for each list + filter, then it is perfectly possible that using a single observable (TodoStore.items$
) might not be a viable solution here and maybe some kind of getTodoList(forFilter)
might be easier/quicker to implement.
Remeber: There is no such thing as "The perfect solution for all cases."
However: Even in this case you could use a store, which could something like this:
interface ITodoListDictionary {
[key: string]: Todo[];
}
@Injectable()
export class TodoStore {
todoLists$: BehaviorSubject<ITodoListDictionary> = new BehaviorSubject<ITodoListDictionary>({});
getListByKey(key: string): Observable<Todo[]> {
return this.todoLists$
.pluck(key)
.distinctUntilChanged() // optional, so you only get the update if there is an actually new list
.share();
}
// this would be called whenever the rest-response for a given list arrives
setListByKey(key: string, list: Todo[]): void {
this.todoLists$.take(1)
.do(dict => {
const newDict = Object.assign({}, dict, {[key]: list});
// if you are using TS2.1 you could also use:
// const newDict = {...dict, {[key]: list}};
this.todoLists$.next(newDict);
})
.subscribe();
}
}
...and in your template you could use it like this
<todo *ngFor="let todo of todoStore.getListByKey(someKey) | async" todo="todo"></todo>
Please keep in mind that is just one possible solution out of many - without seeing your actual application-flow it is hard to tell which might be the best solition.
Upvotes: 1