2

I am building a demo application for a presentation about Angular 2 migration. Part of my app has <input ng-model="" /> and I want to change it to the "Angular 2's way". So, I have two options:

  1. Use the 'formDirectives', which is an overkill for my demo, since I do not have a form here, only some inputs updating some data
  2. Use what Victor Savkin (form Angular 2 team) showed in his (great) post:

<input ([ng-model])="todo.text" />

When ng-model is a directive:

import {Directive, EventEmitter} from 'angular2/angular2';

@Directive({
  selector: '[ng-model]',
  properties: ['ngModel'],
  events: ['ngModelChanged: ngModel'],
  host: {
    "[value]": 'ngModel',
    "(input)": "ngModelChanged.next($event.target.value)"
  }
})
export class NgModelDirective {
  ngModel: any; // stored value
  ngModelChanged: EventEmitter; // an event emitter
}

I've implemented this on my demo project like this:

import {Component, View} from 'angular2/angular2';
import {NgModelDirective as NgModel} from '../ng-model/ng-model';

@Component({
  selector: 'font-size-component',
  properties: [
    'font'
  ]
})
@View({
  template: `<input id="fontSize" class="form-control" name="fontSize" ([ng-model])="font.fontSize"/>`,
  directives: [
    NgModel
  ]
})

export class FontSizeComponent {
  constructor() {
  }
}

My input is getting rendered with the supplied data (the attribute binding [ng-model is working], but the event-binding is not working, giving the following errors:

EXCEPTION: TypeError: Cannot read property 'observer' of undefined

EXCEPTION: TypeError: Cannot read property 'location' of undefined

EXCEPTION: TypeError: Cannot read property 'hostView' of undefined

When I remove the this line events: ['ngModelChanged: ngModel'], from ng-model directive all errors disappears...

I am pretty new to Angular 2 (as we all probably are) and try to understand what am I doing wrong here...

EDIT

OK, so after reading a little more I was convinced that using formDirectives is not such an overkill. My solution is (Using Angular 2 Alpha 35 is now FORM_DIRECTIVES instead of formDirectives):

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

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

export class FontSizeComponent {
  constructor() {

  }
}
Graham
  • 7,431
  • 18
  • 59
  • 84
Yaniv Efraim
  • 6,633
  • 7
  • 53
  • 96
  • 1
    actually the post in Victor Savkin's blog was just an example of how to implement ng-model, angular2 forms come with one implementation included in FORM_DIRECTIVES. It looks the last edit is OK, its the most Angular 1 way AFIK. Did something not work as expected? – Angular University Aug 30 '15 at 12:37

1 Answers1

1

You must initialize events event emitters for your directive. You can do it either in the controller:

import { EventEmitter, Directive } from 'angular2/angular2';

@Directive({
    selector: '[ng-model]',
    properties: ['ngModel'],
    events: ['ngModelChanged: ngModel'],
    host: {
        "[value]": 'ngModel',
        "(input)": "ngModelChanged.next($event.target.value)"
    }
})
export class NgModelDirective {
    ngModel: any; // stored value
    ngModelChanged: EventEmitter; // an event emitter

    constructor() {
        this.newModelChanged = new EventEmitter(); // <== INITIALIZATION
    }
}

Or, if you are using TypeScript, in your properties definition:

// ...
export class NgModelDirective {
    ngModel: any; // stored value
    ngModelChanged = new EventEmitter(); // <== INITIALIZATION
}
alexpods
  • 47,475
  • 10
  • 100
  • 94