Search code examples
angularangular2-databinding

Angular2 Two-way binding and component property updates


Angular2 newbie here.

I have three numeric component properties 'a', 'b' and 'c' where c = a + b. 'a' and 'c' use two-way binding to input statements on the template. If the values are changed in the view, then they also change in the component. However, value 'c' is not updated. How do I get value 'c' to update whenever the values of 'a' or 'b' are changed? Thanks for the help.

    import { Component } from '@angular/core';

    @Component({
        selector: 'my-component',
        template: `
            <input type="number" [(ngModel)]="a"/>
            <input type="number" [(ngModel)]="b"/>
            {{c}}
        `
    })

    export class MyComponent {

       a = 1;
       b = 2;
       c = this.a + this.b;
    }

Solution

  • Setting the value of a class field in TypeScript is actually just syntax sugar for setting it in the constructor:

    export class MyComponent {
       a = 1;
       b = 2;
       c = this.a + this.b;
    }
    
    // is the same as
    
    export class MyComponent {
        constructor() {
            this.a = 1;
            this.b = 2;
            this.c = this.a + this.b;
        }
    }
    

    Now it should be a lot clearer why this doesn't work - the value of c only gets set when the component is initialized! There's no way of Angular knowing that the value of c is dependent on a and b.

    You could get around this by making c a method:

    import { Component } from '@angular/core';
    
    @Component({
        selector: 'my-component',
        template: `
            <input type="number" [(ngModel)]="a"/>
            <input type="number" [(ngModel)]="b"/>
            {{c()}}
        `
    })
    export class MyComponent {
       a = 1;
       b = 2;
    
       c() {
           return this.a + this.b;
       }
    }
    

    The caveat to this is that is that c will get run every time change detection takes place - that's not really an issue with a function as simple as this, but you need to be careful that you're not doing anything too heavy in a binding like this, as it'll slow your app down.

    That said, I don't think you need c at all! It'd be much simpler to just do something like this:

    import { Component } from '@angular/core';
    
    @Component({
        selector: 'my-component',
        template: `
            <input type="number" [(ngModel)]="a"/>
            <input type="number" [(ngModel)]="b"/>
            {{a + b}} or {{a}}{{b}}
        `
    })
    export class MyComponent {
       a = 1;
       b = 2;
    }