• Skip to primary navigation
  • Skip to main content
  • Skip to primary sidebar

I Like Kill Nerds

The blog of Australian Front End / Aurelia Javascript Developer & brewing aficionado Dwayne Charrington // Aurelia.io Core Team member.

  • Home
  • Aurelia 2
  • Aurelia 1
  • About
  • Aurelia 2 Consulting/Freelance Work

Observing Objects and Arrays in Aurelia

Aurelia 1 Tutorials · October 27, 2015

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.

Dwayne

Leave a Reply Cancel reply

11 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Sagar Thakur
Sagar Thakur
7 years ago

What are splices exactly?

0
Dwayne
Dwayne
Author
7 years ago

@Sagar Thakur

Splices returns an object which has some properties detailing the mutation the took place. The number of items added, index and an array of removed items.

0
Holger
Holger
7 years ago

What if I would like to access properties of the class like this.xy=”test” in objectValueChanged(newValue, oldValue)? It seems that “this” is undefined in objectValueChanged.

0
Sagar Thakur
Sagar Thakur
7 years ago

@Holger

You have propertyObserver for that.

0
Jason Drake
Jason Drake
7 years ago

I thought with the 1.0 beta (or perhaps it was the previous releases) there was a change toward using the bindingEngine. This works great for object binding/listening and is much cleaner code wise. I have not tried it on array size changes to know whether or not it will work the same here. My understanding is it takes care of the ObserverLocator stuff under the covers.

0
atsu85
atsu85
6 years ago

@Holger,
> What if I would like to access properties of the class like this.xy=”test” in objectValueChanged(newValue, oldValue)? It seems that “this” is undefined in objectValueChanged.

The problem is that the context is lost when just passing function reference to subscribe method as a callback.

@Dwayne
Could You update the example from
> .subscribe(this.objectValueChanged);
to
> .subscribe((newValue, oldValue) => { this.objectValueChanged(newValue, oldValue)});

That would fix the problem Holger had.

0
Vallabha
Vallabha
6 years ago

I want to call same subscribe event on 4 observable values.

0
vallabha
vallabha
6 years ago

I want to call same subscribe event on 4 observable values.
Is there any short code for this type of scenario.

this.observeMe = ‘myvalue’;
this.observeMe2 = ‘myvalue2’;
this.observeMe3 = ‘myvalue3’;

let subscription = this.bindingEngine
.propertyObserver(this, ‘observeMe observeMe2 observeMe3’)
.subscribe(this.objectValueChanged);

0
Sergiu
Sergiu
6 years ago

How do you test this?

0
Carlos
Carlos
6 years ago

Hi Dwayne, thank you for your excellent posts!

How do these Observables relate to Rxjs? For example, if I want to “import” a bacon.js observable into Rxjs I can do so.

What I’m trying to do is throttle, debounce, filter or map a changed property. I want to put a delay into the event stream so as to no query the server too fast.

Is this possible in Auralia? If not, can I use RxJS and pass in the observable returned from the propertyObserver? As last resort, is there some other way I’ve missed?

Thank you in advance,
Carlos

0
sebah
sebah
4 years ago

how do i observe an entire object not one property

0

Primary Sidebar

Popular

  • I Joined Truth Social Using a VPN and Editing Some HTML to Bypass the Phone Verification
  • Testing Event Listeners In Jest (Without Using A Library)
  • How To Get The Hash of A File In Node.js
  • Thoughts on the Flipper Zero
  • Waiting for an Element to Exist With JavaScript
  • How To Paginate An Array In Javascript
  • How To Mock uuid In Jest
  • How To Decompile And Compile Android APK's On A Mac Using Apktool
  • How To Get Last 4 Digits of A Credit Card Number in Javascript
  • Wild Natural Deodorant Review

Recent Comments

  • CJ on Microsoft Modern Wireless Headset Review
  • Dwayne on Microsoft Modern Wireless Headset Review
  • CJ on Microsoft Modern Wireless Headset Review
  • john on Microsoft Modern Wireless Headset Review
  • Dwayne on Why You Should Be Using globalThis Instead of Window In Your Javascript Code

Copyright © 2023 · Dwayne Charrington · Log in

wpDiscuz