Reputation: 8970
I have a parent component which is loading data from a database. This data comes from my service which returns a promise.
Component:
ngOnInit() {
this._massEmpService.fetchFilterFields()
.then(results => {
this.fields = {
areas: results['areas']['options'],
silos: results['silos']['options'],
departments: results['departments']['options'],
locations: results['locations']['options'],
segments: results['segments']['options'],
roles: results['roles']['options']
};
});
}
Service:
fetchFilterFields() {
return new Promise((resolve, reject) => {
this._http.get(this.baseUrl + '/fetchImportFields', { "headers": this.headers })
.map((result: Response) => result.json())
.subscribe((results) => resolve(results.data));
});
};
I am trying to pass my this.fields
data to a child component but when I try and use the data in the child component, it doesn't appear to have access to it.
Child Component:
@Input() fields: any;
ngAfterViewInit() {
console.log(this.fields); // No data
}
Parent HTML:
<app-import [fields]="fields"></app-import>
I believe this is an async issue but I thought using the afterViewInit
may have solved it. Any thoughts?
Upvotes: 1
Views: 718
Reputation: 13307
My suggestion would be to use shared service with Subject
and Observable
so that the child component variable can subscribe
to the data stream.
With the data binding way, child component is loaded with parent, so when Promise
returns data, child component is not aware of it, hence it needs to be reinitialized to get the data. Observable
and subscription
erases that problem.
I have created this Plunker demo that returns promise data to a child component( with added extra 2000ms of delay). If it works for you, you can easily implement it in you code :)
parent.component.ts:
constructor(private appState: AppState){ }
ngOnInit(){
this.getData();
}
getData(): void {
this.appState
.fetchFilterFields()
.then(data => {
// console.log(data)
this.appState.setData(data);
});
}
service.ts:
private headers = new Headers({'Content-Type': 'application/json'});
private apiUrl = 'api/data';
// Observable string source
private dataStringSource = new Subject<string>();
// Observable string stream
dataString$ = this.dataStringSource.asObservable();
constructor(private http: Http) { }
public setData(value) {
this.dataStringSource.next(value);
}
fetchFilterFields() {
console.log(this.apiUrl);
return this.http.get(this.apiUrl)
.delay(2000)
.toPromise()
.then(response => response.json().data)
.catch(this.handleError);
}
private handleError(error: any): Promise<any> {
console.error('An error occurred', error); // for demo purposes only
return Promise.reject(error.message || error);
}
child.component.ts:
fields: any;
constructor(private appState: AppState){
// this.mylist = this.appState.get('mylist');
this.appState.dataString$.subscribe(
data => {
// console.log("Subs to child" + data);
this.fields = data;
});
}
Upvotes: 1
Reputation: 2599
Use ngOnChanges()
, which is called every time the value of an input property changes.
Upvotes: 0