Howard
Howard

Reputation: 4604

How to make `ngOnChanges` work in `angular2`

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"

Upvotes: 15

Views: 74249

Answers (3)

Rajiv
Rajiv

Reputation: 1295

Looks like you haven't implemented interface OnChanges ..if you implement OnChanges interface then only ngOnChanges will be consider as lifecycle hook function and it will get call on input changes otherwise it will be consider as normal function

Upvotes: 1

Mario Medrano Medrano
Mario Medrano Medrano

Reputation: 339

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.

Upvotes: 3

micronyks
micronyks

Reputation: 55443

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);
    }
}

Upvotes: 17

Related Questions