Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change detection in Angular 2.0

I have an Angular2.0 component:

import {Component, View, FORM_DIRECTIVES} from 'angular2/angular2';

@Component({
  selector: 'font-size-component',
  properties: ['fontSize'],
  events: ['fontSizeChanged']
})
@View({
  template: `<input id="fontSize" [(ng-model)]="fontSize"/>`,
  directives: [FORM_DIRECTIVES]
})
export class FontSizeComponent {
  constructor() {

  }
}

Now, I want this component to trigger an event (using event-binding) when the input changes.

On Angular 1.X I had several options (ng-change or $scope.$wacth). I am looking for a similar solution, so when the input changes I will be able to use eventemitter and trigger an fontSizeChanged event.

Thanks,

Yaniv

like image 222
Yaniv Efraim Avatar asked Aug 30 '15 10:08

Yaniv Efraim


People also ask

How does Angular 2 detect changes?

How is change detection implemented? Angular can detect when component data changes, and then automatically re-render the view to reflect that change.

How many types of change detection strategy are there in Angular 2?

Out of the box, Angular provides two different change detection strategies: Default and OnPush. Each strategy has its own advantages, but sometimes it is easy to miss a nifty optimization opportunity if you stick to the default strategy.

How does Angular detect change detection?

To run the change detector manually: Inject ChangeDetectorRef service in the component. Use markForCheck in the subscription method to instruct Angular to check the component the next time change detectors run. On the ngOnDestroy() life cycle hook, unsubscribe from the observable.


2 Answers

  1. You can use javascript getters and setters. So your component would look like:
import {Component, View, FORM_DIRECTIVES, EventEmitter} from 'angular2/angular2';

@Component({
    selector: 'font-size-component',
    properties: ['fontSize'],
    events:     ['fontSizeChange']
})
@View({
    template: `
        <input id="fontSize" [(ng-model)]="fontSizeModel"/>
    `,
    directives: [FORM_DIRECTIVES]
})
export class FontSizeComponent {
    fontSize: string;
    fontSizeChange = new EventEmitter();

    get fontSizeModel() {
        return this.fontSize;
    }

    set fontSizeModel(value) {
        this.fontSizeChange.next(value);
    }
}

Check out this plnkr

  1. Slightly different solution is to use (input) event binding:
@Component({
    selector: 'font-size-component',
    properties: ['fontSize'],
    events:     ['fontSizeChange']
})
@View({
    template: `
        <input 
          id="fontSize" 
          [value]="fontSize" 
          (input)="fontSizeChange.next($event.target.value)"
        />
    `,
    directives: [FORM_DIRECTIVES]
})
export class FontSizeComponent {
    fontSize: string;
    fontSizeChange = new EventEmitter();
}

See this plnkr

like image 169
alexpods Avatar answered Sep 22 '22 02:09

alexpods


You could also tap into the lifecycle hooks of Angular2. From the documentation:

ngOnChanges(changeRecord) { ... }
Called after every change to input properties and before processing content or child views.

See https://angular.io/docs/ts/latest/guide/lifecycle-hooks.html

Just add this method to your component class:

ngOnChanges(changes: {[propertyName: string]: SimpleChange}) {
  if (changes['fontSize']) { // fire your event }
}

The above guide includes a Plunkr for this: https://angular.io/resources/live-examples/lifecycle-hooks/ts/plnkr.html

like image 30
TylerDurden Avatar answered Sep 20 '22 02:09

TylerDurden