Pass API data from one component into another component?

14,129

First of all, you can see that the console log in component is executed before fetching the data from the backend. This, because this is asynchronous, so it takes a while for the response to arrive.

Second problem, which is related to the same issue, i.e, this being asynchronous, is that you cannot return anything from subscribe, you need to return an Observable to your component and in the component subscribe, either doing it "manually" or then using the async pipe.

If you want to share data to other components after initially getting it another component, what you can do is to use a BehaviorSubject, so declare this in your service:

import {BehaviorSubject} from 'rxjs/BehaviorSubject';

//....

// don't use "any", type your data instead!
private apiData = new BehaviorSubject<any>(null);
public apiData$ = this.apiData.asObservable();

fetchData() {
  return this.http.get('/api/data').map((data) => {
    return data.json();
  })
}

// here we set/change value of the observable
setData(data) { 
  this.apiData.next(data)
}

and in the component where you are fetching the data and want to broadcast to other components, do...

this.dataService.fetchData()
  .subscribe(data => {
    this.data = data;
    // set data in service which is to be shared
    this.dataService.setData(data)
  })

So now we have in this initial component fetched the data, and setting the data in service, which is broadcast to all other components that need it. In those components you just subscribe to this observable.

constructor(private dataService: DataService) { 
  dataService.apiData$.subscribe(data => this.data = data)
}

This solution is based on the idea that you have one component that initially gets the data and then shares it with other components.

Share:
14,129
M Q
Author by

M Q

Updated on July 24, 2022

Comments

  • M Q
    M Q almost 2 years

    I am learning Full-stack Angular4, and wanted to know how would I be able to get data from a get call from one component into another so I can relay the data into the html page with {{data.name}}?

    I tried importing the component into the other component, then setting an empty object into that component.data which holds the data, but I get a empty object as a response back.

    What am I doing wrong?

    UPDATE:

    my shared service:

    import {Injectable} from "@angular/core";
    import {Http, Response, Headers, RequestOptions} from "@angular/http";
    import {Observable} from "rxjs/Rx";
    import 'rxjs/add/operator/map';
    
    @Injectable()
    export class DataService {
        apiData: any;
        constructor(private http: Http) {}
    
        fetchData() {
            return this.http.get('/api/data').subscribe((data) => {
                this.apiData = data.json();
                console.log(this.apiData);
            })
        }
    }
    

    target component:

    import { Component } from "@angular/core";
    import { AllTablesComponent } from '../tables/alltables.component';
    import { DataService } from './../data.service';
    
    
    @Component({
        selector: 'app-target',
        templateUrl: './target.component.html',
        styleUrls: ['./target.component.css']
    })
    export class TargetComponent {
        data: any;
    
        constructor(private dataService: DataService) {
    
            this.data = this.dataService.fetchData();
            console.log("inside target component");
            console.log(this.data);
        }
    }
    

    Screenshot of Empty object from component vs actual data from the data service.

    enter image description here

  • M Q
    M Q over 6 years
    Thank you, this was exactly what I was looking for!
  • AT82
    AT82 over 6 years
    Great! Glad to hear it met your requirements! :)