Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Two-way binding in Angular 2 with NgModel and mutating bound property?

Tags:

angular

I am using Angular 2 beta 5.

Here's my view:

<textarea [(ngModel)]="pendingMessage" (keydown.enter)="sendMessage()"></textarea>

And here's my component:

@Component({
    //...
})
export class AppComponent {
    private _pendingMessage: string;

    public get pendingMessage() {
        return this._pendingMessage;
    }

    public set pendingMessage(value: string) {
        this._pendingMessage = value;
    }

    constructor() {
        this.pendingMessage = "initial stuff"; //this shows up in the text field initially
    }

    public sendMessage() {
        console.log(this.pendingMessage); //here, pending message is indeed whatever I typed in the text field
        this.pendingMessage = "blah";
        //here I expected the textfield to now contain "blah", but it doesn't
    }
}

The whole concept of this two-way binding seems to be working alright. When I type some text in the field and hit enter, I can see that pendingMessage is indeed whatever I typed into the field.

However, in the line below where I try to set the pendingMessage to "blah", I was also expecting this to update the textfield to contain "blah". Why is this not the case? Isn't that the point of two-way bindings?

I know that Angular 2 can't magically know when values change, but I was hoping it would do a dirty check after evaluating the event. Is there any way to make it do such a thing automatically or somehow pick up the change? I would like to avoid using apply.

like image 965
Mathias Lykkegaard Lorenzen Avatar asked Feb 10 '16 18:02

Mathias Lykkegaard Lorenzen


2 Answers

Update

Add ngDefaultControl

<paper-input ngDefaultControl [(ng-model)]="address">

See also https://github.com/angular/angular/issues/5360

**

I guess this is a current limitation of the ngModel implementation. It binds to the value field of the element but for textarea it's the text AFAIR field it should bind to. It seems the textarea fires an event that ngModel listens to which makes it work in one direction.

You can work around this by implementing a custom ValueAccessor

See also
- ngModel custom ValuesAccessor
- Angular 2 custom form input
- Bind angular 2 model to polymer dropdown

like image 121
Günter Zöchbauer Avatar answered Oct 21 '22 12:10

Günter Zöchbauer


For binding textarea values you can use the change-function:

Template

<textarea id="some-value" (change)="doTextareaValueChange($event)">{{textareaValue}}</textarea>

Component

export class AppComponent implements OnInit {
  private textareaValue = '';
  doTextareaValueChange(ev) {
    try {
      this.textareaValue = ev.target.value;
    } catch(e) {
      console.info('could not set textarea-value');
    }
  }
}
like image 24
Markus Brunner Avatar answered Oct 21 '22 14:10

Markus Brunner