简体   繁体   中英

NgModel subscribe only triggers when actual textarea is changed in angular2

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() {
    }

  }

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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM