Binding: Computed Properties

Data-binding computed properties with Aurelia.

Introduction

Sometimes it is desirable to return a dynamically computed value when accessing a property, or you may want to reflect the status of an internal variable without requiring the use of explicit method calls. In JavaScript, this can be accomplished with the use of a getter.

Here's an example Person class that exposes a fullName property that computes it's value using the firstName and lastName properties.


    export class Person {
      firstName = 'John';
      lastName = 'Doe';

      get fullName() {
        return `${this.firstName} ${this.lastName}`;
      }
    }
  

    export class Person {
      firstName = 'John';
      lastName = 'Doe';

      get fullName() {
        return `${this.firstName} ${this.lastName}`;
      }
    }
  

    export class Person {
      firstName: string = 'John';
      lastName: string = 'Doe';

      get fullName(): string {
        return `${this.firstName} ${this.lastName}`;
      }
    }
  

There isn't anything special you need to do to bind to a computed property like fullName. The binding system will examine the property's descriptor , determine that the value of the property is computed by a function and choose the dirty checking observation strategy. Dirty checking means the binding system will periodically check the property's value for changes and update the view as-needed. This means your property's getter function will be executed many times, approximately once every 120 milliseconds. Most of the time this isn't an issue, however, if you're using a lot of computed properties or if your getter functions are sufficiently complex you may want to consider giving the binding system hints on what to observe so that it doesn't need to use dirty checking. This is where the @computedFrom decorator comes in:


    import {declarePropertyDependencies} from 'aurelia-framework';

    export class Person {
      firstName = 'John';
      lastName = 'Doe';

      get fullName() {
        return `${this.firstName} ${this.lastName}`;
      }
    }

    declarePropertyDependencies(Person, 'fullName', ['firstName', 'lastName']);
  

    import {computedFrom} from 'aurelia-framework';

    export class Person {
      firstName = 'John';
      lastName = 'Doe';

      @computedFrom('firstName', 'lastName')
      get fullName() {
        return `${this.firstName} ${this.lastName}`;
      }
    }
  

    import {computedFrom} from 'aurelia-framework';

    export class Person {
      firstName: string = 'John';
      lastName: string = 'Doe';

      @computedFrom('firstName', 'lastName')
      get fullName(): string {
        return `${this.firstName} ${this.lastName}`;
      }
    }
  

@computedFrom tells the binding system which expressions to observe. When those expressions change, the binding system will re-evaluate the property (execute the getter). This eliminates the need for dirty checking and can improve performance. The @computedFrom parameters can be simple property names as shown above or more complex expressions like @computedFrom('event.startDate', 'event.endDate').