So you’ve run into a wall or perhaps just curious on how to expand your observer-fu? Today we are going to be learning how to observe Arrays and Objects in Aurelia.
Many of the concepts you will learn here can be used to use Aurelia components outside of Aurelia, once you understand the rules you can use them to your advantage.
Why you won’t see @observable
here
In another post here I talk about the @observable
decorator and how you can use it, but you won’t see it being used here.
The @observable
decorator and underlying functionality is only for observing class properties, it does not work for arrays or objects (unless you reassign them). When working with arrays, you’ll be; splicing, pushing and popping so it won’t work for those cases.
Observing Arrays
Using the Aurelia Collection Observer we can observe array changes and our subscribe method will return splices.
The syntax kind of looks similar to that of the Event Aggregator, except we’re observing a collection and not working with events.
import {BindingEngine, inject} from 'aurelia-framework';
@inject(BindingEngine)
export class MyClass {
constructor(bindingEngine) {
this.bindingEngine = bindingEngine;
this.theList = [];
let subscription = this.bindingEngine.collectionObserver(this.theList).subscribe(this.listChanged);
// Dispose of observer when you are done via: subscription.dispose();
}
listChanged(splices) {
}
}
What are splices?
You probably assume that “splices” is simply a new array of added items on our callback. This is not the case. The splices argument returns an object with three properties; addedCount
, index
and an array called removed
.
Using these values, we can determine if an item was inserted or removed in an array. In the case of removed
, when we remove an item from an array it will be in this removed
array so we have a record of the deletion.
Observing Object Properties
In Aurelia you can use the BindingEngine class which has a propertyObserver
method which handles observing object properties.
Once again, the syntax looks identical to our array example above, except the propertyObserver
method requires the object we are observing as the first argument and the second argument is a string name of the property.
import {BindingEngine, inject} from 'aurelia-framework';
@inject(BindingEngine)
class MyClass {
constructor(bindingEngine) {
this.bindingEngine = bindingEngine;
this.observeMe = 'myvalue';
let subscription = this.bindingEngine
.propertyObserver(this, 'observeMe')
.subscribe((newValue, oldValue) => { this.objectValueChanged(newValue, oldValue) });
// Dispose of observer when you are done via: subscription.dispose();
}
objectValueChanged(newValue, oldValue) {
console.log(`observeMe value changed from: ${oldValue} to:${newValue}`);
}
}
Unlike our collection observer, we don’t get splices back and get the values themselves. The propertyObserver
works very similar to how @bindable
attributes in custom attributes and elements does with a changed callback.
Conclusion
The collectionObserver
is for collections and not only does it work for arrays, but you can use it on other collection types like a Map
as well. The propertyObserver
is for object properties themselves. That’s all you need to remember.