Reputation: 647
Starting from THIS awesome response, I want to use many DataService instances inside another global service (SystemService) that store and serve many "cacheable" datas. I have imported the DataService file and declared the DataService class in the constructor of my global service but at runtime I receive the error "EXCEPTION: No provider for DataService! (AppComponent -> SystemService -> DataService)" Please,can anyone explain how to use that service inside another global service? Thanks so much.
EDIT , code just for example
---------
// inside bootstrap only the single instance of SystemService
....
bootstrap(AppComponent, [ROUTER_PROVIDERS,HTTP_PROVIDERS,SystemService,provide(LocationStrategy, {useClass: HashLocationStrategy})]).
then((appRef: ComponentRef) => {
appInjector(appRef.injector);
});
-----------
// chacheable and observable generic Data service, I want to use this class in multiple instances one for each cachable and observable data
import {Injectable} from 'angular2/core';
import {Http, Response,Headers, RequestOptions} from 'angular2/http';
import {Observable} from 'rxjs/Observable';
import {Observer} from 'rxjs/Observer';
import 'rxjs/Rx';
@Injectable(
export class CacheableData<T> {
private _apiUrl = 'api/apiweb.php';
private _params:Object;
public data: Observable<T>;
private _dataObserver: Observer<T>;
private _data:T;
constructor (private _http: Http){
this.data = new Observable(observer => this._dataObserver = observer).startWith(this._data).share();
}
public setParams(_params:Object){
this._params=_params;
}
public getData(refresh:boolean=false) {
if (this._data && !refresh) {
console.log('CacheableData - getData -> Cache',this._data);
this._dataObserver.next(this._data);
} else {
console.log('CacheableData - getData -> HTTP...');
this._http.post(this._apiUrl,
JSON.stringify(this._params),
new RequestOptions({ headers: new Headers({'Content-Type': 'application/json'})}))
.map(res=><T>res.json().data)
.do((data) => { })
.subscribe(res => {
// Update cached data
this._data = res;
console.log('CacheableData - getData -> HTTP',this._data);
this._dataObserver.next(this._data);
}, error => console.log('Could not load data.'))
}
}
}
---------
// the global service used to cache and retrieve certain type of datas from the server
@Injectable()
export class SystemService{
constructor (public cacheableData1: CacheableData<IData1>,
public cacheableData2: CacheableData<IData2>) {
....
this.cacheableData1.setParams({
manager:"ApiManager",
action:"GetData1",
WEB_USER_TOKEN:this.user.Token
});
this.cacheableData2.setParams({
manager:"ApiManager",
action:"GetData2",
WEB_USER_TOKEN:this.user.Token
});
.....
}
}
---------
// all views can read and observe chached or fresh data using the systemservice
@Component({
selector: 'home',
templateUrl: 'app/components/views/home/home.component.html'
})
export class HomeComponent implements OnInit{
public data1:IData1;
public data2:IData2;
constructor(private _router: Router,
private _systemService: SystemService) {
}
ngOnInit(){
// data1 observable
this._systemService.cacheableData1.subscribe(data => this.data1=data);
this._systemService.cacheableData1.getData();
// data2 observable
this._systemService.cacheableData2.subscribe(data => this.data2=data);
this._systemService.cacheableData2.getData(true);
}
}
Surely I miss something , but the concept is that I need one global instance of SystemService that use multiple instalces of CacheableData service in order to provide observable and cacheable data for all views and pages...or for other services , why not. I cannot add CacheableData to bootstrab because I need multiple instances, but if I don't, I receive the error message that the provider is missing... Excuse me for the incomplete code but my project is quite complex....
Upvotes: 1
Views: 2456
Reputation: 301
Did you check for circulated referencing e.g. Service A uses Service B, and Service B uses Service A? I have recently experienced this kind of issue, and the error message is the same as yours.
Upvotes: 1
Reputation: 23506
Every service you want to use, depending on the scope, must be added to a providers array.
Either in the bootstrap
call:
bootstrap(AppComponent, [
...,
GlobalService,
DataService
]);
Or in your root component:
@Component({
...,
providers: [..., GlobalService, DataService]
})
export class AppComponent { ... }
Upvotes: 0