mikeesouth mikeesouth - 2 months ago 46
TypeScript Question

Update Aurelia binding when properties change

I'm using Aurelia with TypeScript. I'm trying to bind an object to the view and I want the view to update when I change a property of my object. I know that Aurelia only watches the object and some array manipulations (push, splice etc). I also know that there are some binding helpers such as @computedFrom and using the BindingEngine but I still can't find the best approach when using value converters.

In my example I have class in TypeScript, e.g. "class Car". Then I bind multiple car objects to the view, e.g. ${car1}, ${car2} etc. I add a value converter to present the car, e.g. ${car1 | carPresenter}. This displays the information like this: "A blue car with full tank and three passengers". If I change a car property, e.g. "car1.passengers++" then I want the ${car1 | carPresenter} to update.

Maybe a value converter is the wrong approach? Please advise on better methods if that's the case. I want to present complex objects by showing some of it's properties but not necessarily all of them. And those presentations should update when the underlying properties change.

I have created a gist with a simplified example that illustrates the problem:
https://gist.run/?id=06287de5eb179b32fa0b134eb59ebc68

Answer

There is an additional binding decorator you can leverage: @observable [related docs].

More info: Working With Aurelia @observable (Dwayne's blog is an extremely useful resource for learning Aurelia).

Gist demo: https://gist.run/?id=c359860951717457e630e3fde1a4d6aa

In this demo, the Car object has its own class defined, where all necessary properties have an @observable decorator. Value converter has been replaced by description getter method.

Car class

import { observable } from 'aurelia-framework';

export class Car {
    @observable
    color;

    @observable
    gasLevel;

    @observable
    passengers;

    constructor(data) {
        // ...
    }

    get description() {
        return `A ${this.color} car with ${this.gasLevel} tank and ${this.passengers} passengers`;
    }
}