I'm working on an Angular 2 app, where I want to store some "global variables" (state) across different components. This can be the user's choice of year
and customerId
etc. All components need to access these, for use in GET
calls to the API/backend.
I have implemented router parameters, so it is possible to pass parameters into a component this way, but I find this easier to work with than having to maintain state by forwarding parameters through the router on every click. Hope this makes sense.
Anyway, following this question on StackOverflow, I've set up the following service
:
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/share';
import { Observer } from 'rxjs/Observer';
interface params {
year: string;
customerId: number;
};
@Injectable()
export class ParameterService {
// initial (test) values:
p: params = {
year: "2017",
customerId: 101
};
constructor() {}
}
This seems to work, two ways, allowing my components to get and set parameters like this:
// get global value
this.year = this._parameterService.p['year'];
// set global value
this._parameterService.p['year'] = "2018";
And data binding works, too. This is due to p
being a class (object), rather than just accessing string
year
directly, as I understand it. If I change the year
value from component1
, then component2
(below) will reflect the change:
<h1>Year = {{this._parameterService.p['year']}}</h1>
All I need to do is inject the ParameterService
into any component that needs it, and I'm done. However, I can't figure out how to extend this such that a component will reload (execute another GET
call) with the changed parameter.
For router parameters, a component "subscribes" to the params
in its ngOnInit
method, causing it to "refresh" whenever a route changes:
ngOnInit(): void {
this.sub = this._route.params.subscribe(params => {
this.customerId = params['customerId'];
this.year = params['year'];
this.resetComponentState(); // based on new parameter this time
});
}
resetComponentState(): void {
this._otherService.getDataFromApi(this.year)
.then(
myData => this.myData = myData,
error => this.errorMessage = <any>error);
}
How can I achieve the same thing based on the ParameterService
? Is it possible to somehow "bind" this.year
with this._parameterService.p['year']
in resetComponentState()
? Btw, I have tried doing just that, but to no effect.
UPDATE here is the full component which I want to refresh on parameter change (not just router parameter change):
import { Component, Input, OnInit } from '@angular/core';
import { MyData} from './mydata';
import { ActivatedRoute } from '@angular/router';
import { OtherService } from './other.service';
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';
import { Headers, RequestOptions } from '@angular/http';
import { ParameterService } from '../parameter.service';
import { LocalStorageService } from 'angular-2-local-storage';
@Component({
templateUrl: 'app/test/test.component.html'
})
export class TestComponent implements OnInit {
subscription: any;
customerId: string;
// set getter as a property on the variable `year`:
////year: string;
get year(): string {
console.log("test.component.get()");
const value = this._parameterService.p['year'] + "";
// Any other code you need to execute when the data is changed here
this.getDataFromApi();
return value;
}
private sub: any;
errorMessage: string;
data: MyData[];
constructor(private _otherService: OtherService,
private _parameterService: ParameterService,
private _route: ActivatedRoute,
private _localStorageService: LocalStorageService) { }
getDataFromApi() {
// store route parameters in Local Storage
// if none found, try reading from Local Storage
if (this.customerId == null)
this.customerId = this._localStorageService.get('customerId') + "";
//if (this.year== null)
// this.year = this._localStorageService.get('year') + "";
this._localStorageService.set('customerId', this.customerId);
//this._localStorageService.set('year', this.year);
// try getting YEAR (not customerId, yet) from getter
this._otherService.getDataFromApi(this.customerId, this.year)
.then(
data => this.data = data,
error => this.errorMessage = <any>error);
}
getData(): void{
this.data = this._otherService.getData();
}
resetComponentState(): void {
this.getDataFromApi();
}
ngOnInit(): void {
this.sub = this._route.params.subscribe(params => {
this.customerId = params['customerId'];
//this.year = params['year'];
this.resetComponentState(); // based on new parameter this time
});
}
}