Danny Lagrouw
Danny Lagrouw

Reputation: 418

Why does Angular 2 binding not work in this case? (sub component input field)

I have an (Angular 2) root component called AppComponent that uses another component called Subcomp. App passes an @Input() parameter to Sub. Sub uses this variable for one-way binding in an input field.

Now I...

  1. Set the parameter's value to some initial value ("start"); this is displayed in the input field as expected.
  2. Change the text in the input field to something else.
  3. Click on a button to programmatically reset the value in the AppComponent back to "start".

I then expect the input field to also reset to "start", but instead it keeps displaying the changed text from step 2. Is that correct behavior?

The code:

class Todo {
    constructor(public title: string) {}
}

@Component({
    selector: 'subcomp',
    directives: [FORM_DIRECTIVES],
    template: `New Title: <input type="text" [ngModel]="subtodo.title">`
})
export class Subcomp {
    @Input() subtodo: Todo;
}

@Component({
    selector: 'my-app',
    directives: [Subcomp],
    template: `To do: {{todo.title}}<br/>
               <subcomp [subtodo]="todo"></subcomp><br/>
               <button (click)="update()">Update</button>`
})
export class AppComponent {

    todo: Todo = new Todo('start');

    update() {
        this.todo = new Todo('start');
    }

}

Upvotes: 2

Views: 3945

Answers (1)

Mark Rajcok
Mark Rajcok

Reputation: 364747

Yes it is correct behavior.

Because you are only using one-way databinding in Subcomp, the value of todo.title does not change when you change text in the input field.

When update() is called, a new Todo object is created, but the value of todo.title is start, so when Angular change detection looks at [ngModel]="subtodo.title", it sees no change – the old value of subtodo.title is start as is the current value. Angular change detection compares primitive types (number, string, boolean) by value.

To prove it, try this:

update() {
    this.todo = new Todo('start' + new Date());
}

or try this:

<input type="text" [(ngModel)]="subtodo.title">

Upvotes: 1

Related Questions