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.
For passing the data from the child component to the parent component, we have to create a callback function in the parent component and then pass the callback function to the child component as a prop. This callback function will retrieve the data from the child component.
Props are used for passing data between the components. We usually use it to pass data from the parent component to the child component.
Angular provides the Decorator, @Input(). By using this decorator, we can pass data from the Parent component to the Child component. Angular provides the Decorator, @Output(). By using this decorator, we can pass data from the child component to the parent component.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With