Search code examples
angularhttpgetobservablesubscribe

Angular 6 http + Observable + Subject across multiple components


I'm trying to share data that a my service providers retrieves via a HTTP GET. I get data in my http.service:

@Injectable()
export class HttpService {

  constructor(private http: HttpClient) { }

  public getData4(url: string): Observable<Premium[]> {
    return this.http.get<Premium[]>(url);
  }
}

The routing of app is:

<TabsComponent>
  <TablesComponent> 
  <TablesComponent/>
</TabsComponent>

In tabs.component.ts I have:

 export class TabsComponent implements OnInit {

  myUrl4All = 'http://localhost:8083/RCCT-2.0-SNAPSHOT/rest/v2';
  premiumsO: Premium[] = [];

  constructor(private httpService: HttpService, private entity1Service: Entity1Service) { }

  ngOnInit() {
    this.httpService.getData4(this.myUrl4All).subscribe(data => this.premiumsO = 
    data['premiumList']);
  }
}

In my tabs.component.html I have:

<div>
<app-tables-component></app-tables-component>
</div>

And my tables.component.ts:

export class TablesComponent implements OnInit  {

  constructor() { }

  returnedArray: Premium[] = [];

  ngOnInit(): void {

    this.returnedArray = ?????????
  }

}

And my question is: now I have one http.service with an observable, but I want to catch and display data from http in my tables.component by using subscribe. How I should change my code to do that ?


Solution

  • One simple and quick way is for you to user @Input (remember to import this from @angular/core) on your child component like this:

    export class TablesComponent implements OnInit  {
    
      constructor() { }
    
      @Input()
      returnedArray: Premium[] = [];
    
      ngOnInit(): void { }
    }
    

    and then on your parent template.html pass the parents data like this:

    <div>
        <app-tables-component [returnedArray]="premiumsO"></app-tables-component>
    </div>
    

    EDIT: As per comments below

    Add your Array into your service, make it an observable and subscribe to it. Like:

    @Injectable()
    export class HttpService {
      premiumsO: BehaviorSubject<Premium[]> = new BehaviorSubject<Premium[]>();
    
      constructor(private http: HttpClient) { }
    
      public getData4(url: string): void {
        this.http.get<Premium[]>(url).subscribe(data => {
            this.premiumsO.next(data['premiumList']);
        });
      }
    }
    

    And then in both your parent and child controllers, subscribe to premiumsO like:

    export class TablesComponent implements OnInit  {
    
      constructor(private httpService: HttpService) { }
      private subscription: Subscription;
      returnedArray: Premium[] = [];
    
      ngOnInit(): void {
           this.subscription = this.httpService.premiumsO.subscribe(data => this.returnedArray =  data);
      }
        ngOnDestroy() {
            this.subscription.unsubscribe().        
        }
    }
    

    Do the same thing in your parent. Not sure if this is the right solution but I'd do it like this.