我在下面有这个代码。基本上它是一个带有指令的组件,它可以订阅textarea的模型。
如果我键入textarea,则订阅触发器和控制台日志会发生更改,但是如果模型在外部更改并从组件中的@Input接收,则textarea中的订阅不会触发,即使文本在textarea正在更新。
为什么文本发生变化时不会触发?
@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() {
}
}
答案 0 :(得分:4)
事实上,这是正确的行为。事实上,NgModel
指令会在更新视图时触发update
自定义事件(请参阅源代码中的此行https://github.com/angular/angular/blob/master/modules/angular2/src/common/forms/directives/ng_model.ts#L97):
viewToModelUpdate(newValue: any): void {
this.viewModel = newValue;
ObservableWrapper.callEmit(this.update, newValue);
}
您应该使用表单控件来实现此类处理:
@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');
});
}
}
请参阅此plunkr:https://plnkr.co/edit/5E4JZhm32bu8rrPV9nEf?p=preview。
修改强>
要实现您的期望,您需要利用与ngModel
关联的控件并在其valueChanges
属性中进行订阅。这样,当模型中的值和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);
});
}
}
我更新了我的plunkr:https://plnkr.co/edit/5E4JZhm32bu8rrPV9nEf?p=preview。