1

I'm trying to implement Rxjs based state management in Angular, but I've been stuck with sharing the state with components.

Here it is my implementation:

private readonly _policies = new BehaviorSubject(<Policy[]>([]));

readonly policies$ = this._policies.asObservable();

get policies(): Policy[] {
    return this._policies.getValue();
}

set policies(val: Policy[]) {
    this._policies.next(val);
}

async fetchAll() {
    this.policies = await this._policyService.index().toPromise();
}

async delete(policyId: string): Promise<any> {
    try {
        await this._policyService
            .destroy(policyId)
            .toPromise();

        this.policies = this.policies.filter(policy => policy.id !== policyId);

    } catch (e) {

    }
}

In shell component I just pass the variables to the child component;

<policy-list
   [policies]="_policyStoreService.policies$ | async"
  (deletePolicyEmitter)="_policyStoreService.delete($event)">

FetchAll is called in resolver;

resolve(route: ActivatedRouteSnapshot): any {
    return this._leavePolicyStoreService.fetchAll();
}

I want to keep _policyStoreService.policies$ as shared observable in my components. So, when I add/delete/update policy push that change to all subscribers. Use the service also in lazy loading modules, and fetch the data from api only if it is not loaded before.

The question is how do I use this store service as a singleton service. I've already removed from lazy loading module's providers and insert @Injectable({providedIn: 'root'}) to its metada. But still getting the injection error.

Solution: I just added {providedIn: 'root'} metadata to service dependencies.

6
  • Why you didn't try @ngrx? It's exactly what you need.
    – lagrange-
    Commented Sep 26, 2019 at 6:10
  • I've tried and used ngRx before but it's provide a lot of boilerplate code. I want to keep it simple.
    – esilik
    Commented Sep 26, 2019 at 6:13
  • You just have to create a reducer with the same amount of code. And you don't need to make any architecture decisions :)
    – lagrange-
    Commented Sep 26, 2019 at 6:19
  • What problem are you having? "I'm stuck" is not enough detail for us to help you. If you are wondering if this is a good pattern, the answer is yes - for simple applications, a Subject in a service is a reasonable way of handling state. Here is an article describing this pattern. If you want help with a specific issue you are having, I suggest a StackBlitz that shows the issue.
    – dmcgrandle
    Commented Sep 26, 2019 at 6:33
  • I've updated the question.
    – esilik
    Commented Sep 26, 2019 at 6:39

1 Answer 1

1

You can use a simple RXJS subject in your service:

  1. In your service:

    stateChanges: Subject<any> = new Subject<any>();
    
  2. In your components, where you want to emit a new event to the observable:

    this.yourService.stateChanges.next('Data to emit');
    
  3. In the components when you want to listen to new events:

    this.yourService.stateChanges.subscribe(data => console.log(data));
    

** IMPORTANT: Do not forget to unsubscribe to the observable

1

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.