简体   繁体   中英

Aurelia bindingEngine.propertyObserver - Detect when property changes due to object change

We are using a similar code to detect changes to a specific object property.

import {BindingEngine} from 'aurelia-framework';

class MyViewModel {
    static inject = [BindingEngine];

    constructor(bindingEngine) {
        this.bindingEngine = bindingEngine;
        this.myObject = {observeMe : 'Test' + new Date()};
    }

    attached() {
        this.subscription = this.bindingEngine
            .propertyObserver(this.myObject, 'observeMe')
            .subscribe((newValue, oldValue) => { 
                this.objectValueChanged(newValue, oldValue) 
            });

        setInterval(() => {
            this.myObject.observeMe = 'Test' + new Date();
        }, 2000);
    }

    detached() {
        this.subscription.dispose();
    }

    objectValueChanged(newValue, oldValue) {
        console.log(`observeMe value changed from: ${oldValue} to:${newValue}`);
    }
}

https://discourse.aurelia.io/t/how-to-observe-objects-in-aurelia-using-the-binding-engine/23

The above example works fine and objectValueChanged is triggered when the property observeMe on this.myObject is changed. However due to some circumstances we would sometimes like to replace the entire object but still fire an event. Example:

setInterval(() => {
    this.myObject = { observeMe : 'Test' + new Date()}
    //Object.assign does not work either
    //this.myObject = Object.assign({ observeMe : 'Test' + new Date()}, this.myObject);
}, 2000);

This does not trigger objectValueChanged . What could we do instead if we need to catch both property changes or if the entire object is changed?

Right now we have solved it by not creating new objects but instead replace values like this. However it would be a lot easier for us if we could track that the object was changed as well.

Object.keys(this.myObject).forEach((key) => {
    this.myObject[key] = newMyObject[key];
});

You can use expressionObserver on BindingEngine to observe a long path with many accessors. Sandbox example here: https://codesandbox.io/s/x3qz6w2k6w

Basically binding engine gives a shortcut to do it that reads like the following:

bindingEngine.createObserverFor(someObject, 'at.this.property.path');

The value will be the value of final property in the path, and it's guarded against null / undefined by default so you will get undefined if any of property access along the path returns null / undefined

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM