Aurelia: How to observe a specific property of a bound object (custom attribute)

1.2k views Asked by At

I am trying to observe a change event of a object specific property bound to a custom attribute. I use the bindable tag for this.

The object

var information =  {
    name: 'foo',
    description: 'bar',
    age: 12
};

The element

<div my="info: information;"></div>

The attribute

@customAttribute('my')
export class MyCustomAttribute {

    @bindable({
        changeHandler: 'change'
    }) 
    public info: any;

    private change(): void {
        console.log('info has changed')
    }    
}

Above example only fires the change handler once. But I need it to fire every time when one of the properties on the info object changes. In my use-case it doesn't matter which property changes, I just need to know when a property changes.

Any idea on how to that?

FYI => A different approach would be to create a separate property on the view model (and use bindable tags on that) instead of using the object, but I rather not do that because it would make the plumbing of the attribute tedious in the HTML (because of the amount of properties).

2

There are 2 answers

0
Tom Aalbers On BEST ANSWER

I managed to solve it this way; (thanks to the comment of Marc Scheib)

import { BindingEngine, Disposable } from 'aurelia-framework';

@customAttribute('my')
export class MyCustomAttribute {

    @bindable public info: any;

    private subscription: Disposable;

    constructor(
        private binding_engine: BindingEngine
    ) { }

    public attached(): void {
        this.subscription = this.binding_engine
            .propertyObserver(this.info, 'name')
            .subscribe(() => this.change())
    }

    private change(): void {
        console.log('info name property has changed')
    }    

    public detached(): void {
        this.subscription.dispose();
    }
}
2
Sean Hunter On

As far as I'm aware there is no way to bind to nested property values, unfortunately. The observable system is based on properties that can be re-written by Aurelia to notify the framework when they are changed. Because you'll be updating the nested properties rather than the info property itself, no notifications will be fired. I think the best approach would be to do as you mentioned in the FYI and create a separate property that you would then observe.

A note on style. You may already be aware of this, but you don't actually need this @customAttribute('my') decorator. This will be the default behavior of Aurelia's convention system, so you could leave it out and the end result will be the same.