Angular 2: Создание "сервиса глобальных параметров" и подписка на его параметры

Я работаю над приложением Angular 2, где я хочу хранить некоторые "глобальные переменные" (состояние) для разных компонентов. Это может быть выбор пользователя year а также customerId и т. д. Все компоненты должны иметь к ним доступ для использования в GET вызовы API/ Backend.

Я реализовал параметры маршрутизатора, так что можно передавать параметры в компонент таким образом, но мне легче работать с ним, чем поддерживать состояние, передавая параметры через маршрутизатор при каждом щелчке. Надеюсь, это имеет смысл.

Во всяком случае, после этого вопроса на Stackru, я настроил следующее 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() {}
}

Кажется, это работает двумя способами, позволяя моим компонентам получать и устанавливать параметры следующим образом:

    // get global value
    this.year = this._parameterService.p['year'];

    // set global value
    this._parameterService.p['year'] = "2018";

И привязка данных тоже работает. Это связано с p быть классом (объектом), а не просто обращаться к stringyear напрямую, насколько я понимаю. Если я изменю year значение от component1, затем component2 (ниже) будет отражать изменение:

  <h1>Year = {{this._parameterService.p['year']}}</h1>

Все, что мне нужно сделать, это ввести ParameterService в любой компонент, который нуждается в этом, и я готов. Тем не менее, я не могу понять, как расширить это так, чтобы компонент перезагрузился (выполнить другой GETвызов) с измененным параметром.

Для параметров маршрутизатора компонент "подписывается" наparamsв егоngOnInitметод, заставляющий его "обновляться" при изменении маршрута:

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);
}

Как я могу добиться того же, основываясь на ParameterService? Можно ли как-то "связать" this.yearс this._parameterService.p['year']вresetComponentState()? Кстати, я пытался сделать это, но безрезультатно.

ОБНОВЛЕНИЕ- это полный компонент, который я хочу обновить при изменении параметров (а не только при изменении параметров маршрутизатора):

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
        });
    }
}

1 ответ

Используйте геттеры и сеттеры. Что-то вроде этого:

// get global value
get year() {
   const value = this._parameterService.p['year'];
   // Any other code you need to execute when the data is changed here
   this.getDataFromApi();
   return value;
}

set year(value) {
   this._parameterService.p['year'] = value;
}

У меня есть запись в блоге об этом здесь: https://blogs.msmvps.com/deborahk/build-a-simple-angular-service-to-share-data/

И плункер здесь: https://plnkr.co/edit/KT4JLmpcwGBM2xdZQeI9?p=preview

Другие вопросы по тегам