Reputation: 10713
I stumbled on this Plunkr http://plnkr.co/edit/yMBoVkxohwhPig5COgkU?p=preview
It shows an observable data service. The part where my question is about shows:
export class TodoService {
private _todos$: Subject<Todo[]>;
private baseUrl: string;
private dataStore: {
todos: Todo[]
};
constructor(private http: Http) {
this.baseUrl = 'http://56e05c3213da80110013eba3.mockapi.io/api';
this.dataStore = { todos: [] };
this._todos$ = <Subject<Todo[]>>new Subject();
}
get todos$() {
return this._todos$.asObservable();
}
loadAll() {
this.http.get(`${this.baseUrl}/todos`).map(response => response.json()).subscribe(data => {
this.dataStore.todos = data;
this._todos$.next(this.dataStore.todos);
}, error => console.log('Could not load todos.'));
}
The code above runs fine. However when I replace the loadAll
with code which doesn't make an http call:
loadAll() {
this.dataStore.todos = [{ 'id': '1', 'createdOn': 1472831416, 'value': 'value 1' }, { 'id': '2', 'createdOn': 1472831360, 'value': 'value 2' }, { 'id': '4', 'createdOn': 1472831771, 'value': 'value 4' }, { 'id': '5', 'createdOn': 1472831716, 'value': 'value 5' }, { 'id': '6', 'createdOn': 1472831658, 'value': 'value 6' }];
this._todos$.next(this.dataStore.todos);
}
It stops notifying the frontend as shown in this Plunkr: http://plnkr.co/edit/ObiWt2cm6sGSgW2Hf5ya?p=preview
Could someone explain why this is and how I can make it work?
Upvotes: 3
Views: 4203
Reputation: 7246
The Subject
expects one item to be passed to it with on next, not an array of items. What you are doing is similar to:
let subject = new Subject<{ message: string }>();
subject.onNext([{ message: 'test one' }, { message: 'test two' }]);
This is an error and should generate an error on compilation.
As I mentioned onNext
expects one item of its generic type, not an array of items. So something like this would be correct:
let subject = new Subject<{ message: string }>();
subject.onNext({ message: 'test one' });
If you want to create an observable
from the items in an array you have a few options, the first one is to loop over the array and call onNext
for each item in the array, like so:
let subject = new Subject<{ message: string }>();
let items = [{ message: 'test one' }, { message: 'test two'}];
items.forEach(item => subject.onNext(item));
Another way would be to create an observable from the array:
let subject = new Subject<{ message: string }>();
let items = [{ message: 'test one' }, { message: 'test two'}];
let itemsObservable = Observable.from(items);
In this example itemObservable
would replace your:
get todos$() {
return this._todos$.asObservable();
}
and become something like:
get todos$() {
return this.itemObservable;
}
hope this clears some things up. The basic problem in your solution is basically that you are misunderstanding how a Subject
works.
Upvotes: 2