Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make `ngOnChanges` work in `angular2`

Tags:

angular

My child component as following:

'use strict';

import {Component, Input, OnInit, OnChanges, ChangeDetectionStrategy, ElementRef} from 'angular2/core';

@Component({
    changeDetection: ChangeDetectionStrategy.OnPush,
    selector: 'my-app',
    template: ''
})
export class MyApp implements OnInit {

    @Input() options: any;

    constructor(private el: ElementRef) {
    }

    ngOnInit() {

    }

    ngOnChanges(...args: any[]) {
        console.log('changing', args);
    }

}

And Parent component as following:

'use strict';

import {Component, Input} from 'angular2/core';
import {MyApp} from './MyApp';

@Component({
    selector: 'map-presentation',
    template: `<my-app [options]="opts"></my-app>
    <button (click)="updates($event)">UPDATES</button>
    `,
    directives: [MyApp]
})
export class MainApp {

    opts: any;

    constructor() {
        this.opts = {
            width: 500,
            height: 600
        };
    }

    updates() {
        console.log('before changes');
        this.opts = {
            name: 'nanfeng'
        };
    }

}

Each time while i clicked the "UPDATES" button, the ngOnChanges method never be called, but why?

I angular version i am using is "2.0.0-beta.8"

like image 685
Howard Avatar asked Mar 06 '16 05:03

Howard


People also ask

Why ngOnChanges is not getting called?

Current behaviorWhen dynamically creating components, manually changing a property of a child component of that created component and then triggering changeDetection, ngOnChanges on this child component does not get called.

How do you use ngOnChanges?

When should you use ngOnChanges? Use ngOnChanges whenever you want to detect changes from a variable decorated by @Input. Remember that only changes from the parent component will trigger this function. Also remember that changes from the parent still update the child value even without implementing ngOnChanges.

How does ngOnChanges work in Angular?

The ngOnChnages is a life cycle hook, which angular fires when it detects changes to data-bound input property. This method receives a SimpeChanges object, which contains the current and previous property values. The child Component decorates the property using the @Input decorator.

Does ngOnChanges fire Oninit?

ngOnInit DOES NOT FIRE.


2 Answers

It's working
app.ts

import {Component} from 'angular2/core';
import {child} from 'src/child';
@Component({
  selector: 'my-app',
  providers: [],
  template: `
    <child-cmp [options]="opts"></child-cmp>
    <button (click)="updates($event)">UPDATES</button>
  `,
    directives: [child]
})
export class App {
   opts: any;

   constructor() {
      this.opts = {
          width: 500,
          height: 600
      };
   }

   updates() {
      console.log('after changes');
      this.opts = {
          name: 'micronyks'
      };
   }
};

child.ts

import {Input,Component,Output,EventEmitter} from 'angular2/core';
import {Component, Input, OnInit, OnChanges, ChangeDetectionStrategy, ElementRef} from 'angular2/core';
@Component({
    selector: 'child-cmp',
    changeDetection: ChangeDetectionStrategy.OnPush,
    template: `

    `
})
export class child   { 
    @Input() options: any;

    ngOnChanges(...args: any[]) {
        console.log('onChange fired');
        console.log('changing', args);
    }
}
like image 167
Nikhil Shah Avatar answered Sep 24 '22 01:09

Nikhil Shah


Well it works with "input properties", this means with those passed in this format: @Input() myVariable: string;

I made it work normally when this input value is a string, number or boolean, but with objects I still do not now what's going on.

So, in the "AppComponent" template (the .html) can go something like this:

<input type="text" [(ngModel)]="name"> // name is a string property of the AppComponent
<app-test [myVal]="name"></app-test>

And the "test component" can look like this:

import {Component, Input } from '@angular/core';

@Component({
  selector: 'app-test',
  template: `
    <div> TEST COMPONENT {{myVal}}</div>
  `,
  styles: []
})
export class TestComponent {
  constructor() { }  
  ngOnChanges(changeRecord: SimpleChanges) {
    console.log('It works!');
    /* changeRecord will have a property for each INPUT named the same
    as the input. These are added to changeRecord when the input
    gets a value */
    if(typeof changeRecord.myVal !== 'undefined){
          console.log('myVal = ', changeRecord.myVal.currentValue);
    }

  } 
  @Input() myVal: string;  
}

Cheers.

like image 42
Mario Medrano Medrano Avatar answered Sep 21 '22 01:09

Mario Medrano Medrano