I could set up the property observation in a view model, such as regions-list.js above, but it seems that it this should be the responsibility of the underlying model object.
It seems to me that you want some observable properties. If that’s all what you need, then you can simply use the @observable decorator on your property. That should work, irrespective of whether your class is a view model, or not. And you don’t have to bother about the BindingEngine. That is useful where you don’t have access to source code of the class where you want to observe property, or don’t want to put Aurelia dependency for whatever reason.
Thanks for your help.
So, the @observable is just for observing changing properties of a class?
My class has a property called data which is a Map where the values are regular JS objects (created when I dynamically load some JSON data). I want to observe the ‘show’ property of every object in this Map. The UI is a bit like a hierarchy browser - loading ‘folders’ then listening for each one to be expanded -> then loading child objects.
Currently I’m setting this up using the bindingEngine like this in the model view:
// for each object in the Map, observe the 'show' property.
this.regions_info.data.forEach((roi, roi_id) => {
this.observers.push(this.bindingEngine.propertyObserver(roi, 'show').subscribe(
(newValue, oldValue) => {
this.handleRoiShow(newValue, oldValue, roi_id);
}));
});
Using the subscribe() closure allows me to pass an additional roi_id parameter to the handler.
This is working but I would prefer it if the regions_info class itself was able to setup these observers.
class Region {
@observable public show: boolean = false;
public deleted: number = 0,
public constructor(
public name: string,
public shapes: Shapes, // assuming the Shapes type exists
){}
private showChanged(){
// handle the change event here;
// or publish the `{name}:show:changed` event from here to notify the actual handler(s).
}
}
Then you can use the following to set values in the map.
this.data.set(roiId, new Region(name, shapes));
I have used TS syntax, but I think you can transfer that to JS as well. Does this approach help you?