What is the best practice to store (and share) initial values in an Angular 2 application using a service? I have a service that loads much data from a server as resources,configurations and other that are array and objects. I do not want to load this data each time I load a component or when I route to a view, I just want to use these objects and array already loaded when the application starts, and optionally reload if needed. The question is where is the right place to store this values and how to share across components that use the service? Thanks.
Asked
Active
Viewed 3.5k times
3 Answers
28
Gunter is completely right regarding shared services!
Here are some more details for an HTTP that relies on observables and cached data for next calls:
export class SharedService {
constructor(private http:Http) {
}
getData() {
if (this.cachedData) {
return Observable.of(this.cachedData);
} else {
return this.http.get(...)
.map(res => res.json())
.do((data) => {
this.cachedData = data;
});
}
}
}

Thierry Templier
- 198,364
- 44
- 396
- 360
-
Your implementation is very interesting! So all components can use "subscribe" function to load fresh or cached data , I'm right? thanks so much – Massimo Magliani Mar 15 '16 at 07:32
-
Yes, exactly. It's completly transparent for the subscriber ;-) You're welcome! – Thierry Templier Mar 15 '16 at 08:05
-
I'm trying to implement this structure, my only doubt is that my API returns an objects array but in my "GetData" but I want return just one object (that match a certain index for example), and also propagate changes about that object to every components when server return new object array (after a "reload" function inside the service for example). Do you have any suggestions to accomplish this result? Again thanks for your time. – Massimo Magliani Mar 15 '16 at 10:38
-
@MassimoMagliani, create an observable (a new one that is not related to the observable returned by `http.get()`) inside your service and have your components subscribe to it. Whenever you make a server request and then get data back from the server, push the new data into that observable: `_observer.next(newData)`. See http://stackoverflow.com/a/35568924/215945 for an example. You'll probably also need to `share()` this observable since you have multiple subscribers. See http://stackoverflow.com/a/35704827/215945. – Mark Rajcok Mar 15 '16 at 15:21
-
@MassimoMagliani, this answer by Thierry might help you also: http://stackoverflow.com/a/35983567/215945 – Mark Rajcok Mar 15 '16 at 15:25
-
3@ThierryTemplier, this doesn't account for two calls to happen near simultaneously when the data is not cached yet right? – tylerjgarland Feb 03 '17 at 18:00
15
You have to think about shared service and make sure only single instance is shared among components.
shared service and shared object demo
Note:
don't forget to register service in bootstrap function. Observe code deeply. you will get what you want. Routing part is not demonstrated. Surf plunk for further implementation
service.ts
import {Component, Injectable,Input,Output,EventEmitter} from 'angular2/core'
import {Router} from 'angular2/router';
import {Http} from 'angular2/http';
export interface Info {
name:string;
}
@Injectable()
export class NameService {
constructor(http:Http;router:Router)
{
this.http=http;
// you can call server resource from here and store it down to any variable.
}
info: Info = { name : "Jack" };
change(){
this.info.name = "Jane"; // this.info is shared among components.
}
}

micronyks
- 54,797
- 15
- 112
- 146
-
1If you refresh the page old variable is back because of info: Info = { name : "Jack" }; – Diego Sep 19 '17 at 10:04
13
The right place is definitely a service. If you add this service as provider at one place only, one instance is shared with the whole application. If you add it to providers on each component, each component gets its own instance - which is what you want to avoid
bootstrap(AppComponent, [HTTP_PROVIDERS, MyService]);
@Component({
selector: 'some-comp',
providers: [/* don't add MyService here !! */]})
class MyComponent {}

Günter Zöchbauer
- 623,577
- 216
- 2,003
- 1,567
-
Would it not be better to provide the service to only the highest component in the tree that needs it? Then unrelated components are unaware of your newly created service? – marked-down Jul 08 '16 at 22:26
-
Exactly, if only one component needs the service. It's just one of the most frequent errors that services are provided on every component that injects it, even when a shared instamce is required, therefore I'm a bit cautious to suggest to provide at a component. – Günter Zöchbauer Jul 09 '16 at 05:10
-
@GünterZöchbauer Can you please provide an example for sharing the data from a base component. – Vinay Pratap Singh Bhadauria May 31 '17 at 09:53
-
@VinaySingh what do you mean with base component? Please provide more information about your use case. Perhaps it's better to create a new question with full details of your requirements. – Günter Zöchbauer May 31 '17 at 17:19
-
@GünterZöchbauer Thanks! I did it referencing the answers(This and other SO questions) from you and Theirry Templier. – Vinay Pratap Singh Bhadauria Jun 02 '17 at 05:12