0

I an looking for recommendation how the code may be simplified if there is a need to to subscribe to the same data in multiple Angular smart components.

For example, this code is the same:

public item: Item | undefined;

public ngOnInit(): void {
  this.items$.subscribe(a => this.item = a);
}

Once I add unsubscribe on ngOnDestroy, the code duplication increases even more.

Is it possible to use simplify component somehow? Subscribe in root AppComponent or use Value Providers?

Pipes, in my understanding, are not an option in cases like handling button clicks/hammerjs gestures/code in ngOnChanges, when this.item is used inside a component, not template.

Zygimantas
  • 8,547
  • 7
  • 42
  • 54

1 Answers1

1

To share an Observable for multiple observers, you need something like the share operator.

Example:

 import {Observable} from 'rxjs';
    import {share} from 'rxjs/operators'

    export class dataService{
    public data$=Observable<Idata[]>
             constructor(http:HttpClient)
            {
               this.data$=this.http.get<Idata[]>('https://jsonplaceholder.typicode.com/posts').pipe(share());
             }
             public getPosts():Observable<Idata[]>
                {
                    return this.data$
                }}

This operator is a specialization of publish which creates a subscription when the number of observers goes from zero to one, then shares that subscription with all subsequent observers until the number of observers returns to zero, at which point the subscription is disposed.

Refer this for more

Since you want to get resolved data before navigating to the new route you could use Resolve guard

which Performs route data retrieval before route activation. you can access the resolved data using the data property of ActivatedRoute’s snapshot object or subscribe to ActivatedRoute data Property which holds the static and resolved data of the current route

resolve.service.ts:

import { Injectable } from '@angular/core';
    import { Resolve } from '@angular/router';
   import {Observable} from 'rxjs';

    @Injectable()
    export class resolver implements Resolve<Observable<any>> {
      constructor(private service:Service) {}

      resolve() {
        return this.dataService.getdata();
      }
    }

routes.module.ts:

 {
            path: 'home',
            component: HomeComponent,
            resolve: {
                data: resolver,
            },
        },

.component.ts:,

  constructor( private route:ActivatedRoute) {
                 this.route.data.subscribe(value=>{
                       console.log(value);
                       });}

STACKBLITZ DEMO

Refer

1. fetch-data-before-navigating

  1. Route Resolvers
Vikas
  • 11,859
  • 7
  • 45
  • 69
  • And inject dataService into smart component to subscribe again? I don't see code reuse here. Or am I missing something? – Zygimantas Jun 05 '18 at 15:15
  • well yeah, angular style guide says *Logic may be reused by multiple components when placed within a service and exposed via a function.* so inject the service and subscribe – Vikas Jun 05 '18 at 15:20
  • even persisting the data in local storage would require you to inject it in the component in order to get the values – Vikas Jun 05 '18 at 15:21
  • I hope [this](https://stackoverflow.com/a/50631080/5695162) will give you a clearer picture – Vikas Jun 05 '18 at 15:24
  • No no, my aim is to do something like we have with @Input, but on the higher level. Maybe AppComponent may be responsible for subscription and pass resolved data to router-outlet. Or maybe the value is resolved even on higher level and injected as value. – Zygimantas Jun 05 '18 at 15:25
  • Ohh I see now I understand – Vikas Jun 05 '18 at 15:25
  • Take a look at [this](https://stackoverflow.com/a/50545563/5695162) and [this](https://alligator.io/angular/route-resolvers/) – Vikas Jun 05 '18 at 15:28
  • Mate,I have updated my answer upvote and mark it if it is helpful :) – Vikas Jun 05 '18 at 16:01