I have been looking for some reason of this behavior, the value of a Input() property in a child component 'Param' is not been updated at the right time, I need to use the updated value to call a service as a parameter. By clicking the 'update child value' button the LOG B is displayed first (with an old value) after that the LOG A is displayed (LOG A it's in the setter of the property).
Parent component
@Component({
selector: 'parent',
template: `
<child #child [param]="parentParam"></child>
<button (click)="updateChildValue()">Update child value</button>
`})
export class Parent {
@ViewChild('child') child: Child;
public parentParam: number;
public updateChildValue() {
this.parentParam = 9;
this.child.showParam();
}
}
the child component
@Component({
selector: 'child',
template: '' })
export class Child {
private _param: number;
public get param() : number {
return this._param;
}
@Input('param')
public set param(v : number) {
this._param = v;
console.log('LOG A');
console.log(this.param);
}
public showParam() {
console.log('LOG B');
console.log(this.param);
//I need to call a service using the latest value of param here...
}
}
The desired behavior is to have first the value of the param updated and then use that value as a parameter on a service. LOG A then LOG B
Working with @ViewChildren is similar to @ViewChild, but the difference between the two is @ViewChildren provides a list of element references rather than returning a single reference. It is used to reference multiple elements. We can then iterate the list of the element referenced by the variable.
ViewChildlinkProperty decorator that configures a view query. The change detector looks for the first element or the directive matching the selector in the view DOM. If the view DOM changes, and a new child matches the selector, the property is updated.
While Angular inputs/outputs should be used when sharing data to and from child components, ViewChild should be used when trying to utilize properties and methods of the child component directly in the parent component.
Using @Input()
implies you are relying on Angular2 mechanism to propagate the value changes, which means you should not expect your changes to take immediate effect. In fact, your this.parentParam = 9;
will go through a whole Angular2 cycle to update your child's param
and the showParam()
function will always be executed first.
To achieve your task, you have 2 choices:
1) Add parameter directly to your showParam
, as in:
// child component
public showParam(newVal: number) {
this._param = newVal;
// do your service call here
}
// parent component
public updateChildValue()
{
this.parentParam = 9;
this.child.showParam(9);
}
2) Leverage ngOnChanges
on your Child
component. This function will be invoked by Angular2 every time there's a change to any @Input
. However, if you have more than 1 input, this could be problematic.
ngOnChanges(changes) {
console.log(this.param); // new value updated
}
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