I have a parent component which is getting data from a server through a service. I need some of this data to be passed to the Child component.
I\'ve been trying to p
@Component({
selector: 'test-child',
template: `
<!-- Content for child.... -->
`
})
export class ChildComponent implements OnChanges {
@Input() childData: any;
ngOnChanges() {
console.log(childData); // logs undefined
}
}
This is supposed to be like this, no? I hope this might be the problem.
ngOnChanges() {
console.log(this.childData); // reference with this
}
I'm assuming that the child is getting a subset of the parents data, potentially from a user action (like loading a form when a user clicks on a grid row). In this case I would use an event.
Have the parent fire an event, maybe dataSelected, and the contents of the event would be the data that was selected.
Then have the child listen for those events and when fired load the data from the event into the model.
This will help decouple your components, which always a good idea.
Since data is undefined at start, you can postpone it with *ngIf='data'
<div *ngIf='data'>
<test-child [childData]="data"></test-child>
</div>
Or you can implement ControlValueAccessor on your component and pass it by ngModel with ngModelChange
<test-child [ngModel]="data?" (ngModelChange)="data? ? data= $event : null"></test-child>
you can use ngOnChanges
to get data like below,
ngOnChanges() {
if(!!childData){
console.log(childData);
}
}
OnChanges
Angular calls its ngOnChanges method whenever it detects changes to input properties of the component (or directive).
Read more about it here.
Update
ngOnChanges
will only fire if you change entire object, if you want to just update property of the bound object not entire object you have two options,
either bind the property directly in the template, make sure to use ?
like {{childData?.propertyname}}
or you can create a get property depending upon childdata object,
get prop2(){
return this.childData.prop2;
}
Copmlete Example,
import { Component, Input } from '@angular/core';
@Component({
selector: 'my-app',
template: `<h1>Hello {{name}}</h1>
<child-component [childData]='childData' ></child-component>
`
})
export class AppComponent {
name = 'Angular';
childData = {};
constructor(){
// set childdata after 2 second
setTimeout(() => {
this.childData = {
prop1 : 'value of prop1',
prop2 : 'value of prop2'
}
}, 2000)
}
}
@Component({
selector: 'child-component',
template: `
prop1 : {{childData?.prop1}}
<br />
prop2 : {{prop2}}
`
})
export class ChildComponent {
@Input() childData: {prop1: string, prop2: string};
get prop2(){
return this.childData.prop2;
}
}
Here is the Plunker!
Hope this helps!!
At the time your ChildComponent (you called it also ParentComponent, but i guess it's a typo) gets initialized and executes its ngOnInit, there is no data in your parent avaible since your service will still be out getting your data. Once your data is there it will be pushed to the child.
What you can do depends on your usecase..
If you just want to display the data in your ChildComponent template, you could use the elvis operator (?
). Something like: {{ childData?}}
or {{ childData?.myKeyName }}
...
If you want to do some other stuff, you may use a setter in your ChildComponent. It will intercept the input change and give you the opportunity to alter/test/"do what ever you want" with it before you do other things with it in your ChildComponent.. eg.:
@Component({
selector: 'test-child',
template: `
<!-- Content for child.... -->
`
})
export class ChildComponent implements OnInit {
private _childData: any;
@Input()
set childData(parentData: any) {
// every time the data from the parent changes this will run
console.log(parnetData);
this._childData = parentData; // ...or do some other crazy stuff
}
get childData(): any { return this._childData; }
ngOnInit() {
// We don't need it for that...
}
}
or use ngOnChanges
as Madhu mentioned.
You also might want to take a look at the cookbook entry for Component Communication in the official docs.