Reputation: 3223
I have this code below. Basically it is a component with a directive that subscribes to the model of the textarea.
If i type in the textarea, the subscribe triggers and the console log changes, however if the model is changed externally and received from the @Input in the component the subscribe in the textarea doesn't trigger, even though the text in the textarea is updating.
Why does it not trigger whenever the text is changing?
@Directive({
selector: 'textarea[mydir]',
host: {'ngFormControl':'myCtrl'}
})
class MyDirective {
myCtrl: any;
constructor(){
this.myCtrl = new Control();
this.myCtrl.valueChanges.subscribe(
(data) => {
console.log('Model change', data);
});
}
}
// Project card
@Component({
selector: 'four',
providers: [],
styles: [ require('./four.scss') ],
directives: [NgFor, MyDirective],
template: `
Hello, this is working! <br>
<textarea mydir [(ngModel)]="pp.status"></textarea>
`,
})
export class Four {
@Input() pp: Array<any>;
constructor() {
}
}
Upvotes: 4
Views: 4090
Reputation: 202276
In fact, it's the correct behavior. As a matter of fact, the NgModel
directive triggers when the update
custom event (see this line https://github.com/angular/angular/blob/master/modules/angular2/src/common/forms/directives/ng_model.ts#L97 in the source code) when the view is updated:
viewToModelUpdate(newValue: any): void {
this.viewModel = newValue;
ObservableWrapper.callEmit(this.update, newValue);
}
You should use a form control to implement such processing:
@Component({
selector: 'four',
directives: [MyDirective],
template: `
Hello, this is working! <br>
<textarea mydir [(ngModel)]="pp.status" [ngFormControl]="myCtrl"></textarea>
`,
})
export class Four {
@Input() pp;
constructor() {
this.myCtrl = new Control();
this.myCtrl.valueChanges.subscribe(
(data) => {
console.log('Model change');
});
}
}
See this plunkr: https://plnkr.co/edit/5E4JZhm32bu8rrPV9nEf?p=preview.
Edit
To achieve what you expect, you need to leverage the control associated with the ngModel
and subscribe in its valueChanges
property. This way, you will be notified both when the value is updated in the model and from the textarea:
@Directive({
selector: 'textarea[mydir]',
})
class MyDirective {
constructor(@Optional() public model: NgModel){
this.model.control.valueChanges.subscribe(data => {
console.log('value updated - new value = '+data);
});
}
}
I updated my plunkr: https://plnkr.co/edit/5E4JZhm32bu8rrPV9nEf?p=preview.
Upvotes: 4