Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

viewchild input property not updated when needed angular 2

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

like image 699
destined Avatar asked Oct 26 '16 22:10

destined


People also ask

What is the difference between ViewChild and ViewChildren?

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.

How does ViewChild work in Angular?

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.

What is the difference between @ViewChild and @input?

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.


1 Answers

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
}
like image 178
Harry Ninh Avatar answered Oct 13 '22 01:10

Harry Ninh