This site runs best with JavaScript enabled.

Observing Arrays in Aurelia


If you're struggling to observe array data changes in Aurelia, check out these code snippets.

If you want to observe changes to an array in Aurelia, you can't simply use the @observable decorator as it won't recognize mutations to the array. Instead, you need to use the collectionObserver in the BindingEngine.

Example:

1import {BindingEngine, inject} from 'aurelia-framework'
2
3@inject(BindingEngine)
4export class App {
5 constructor(bindingEngine) {
6 this.bindingEngine = bindingEngine
7 this.data = []
8 }
9
10 attached() {
11 this.subscription = this.bindingEngine
12 .collectionObserver(this.data)
13 .subscribe(this.dataChanged)
14 }
15
16 detached() {
17 this.subscription.dispose()
18 }
19
20 dataChanged(splices) {
21 console.debug('dataChanged', splices)
22 }
23}

There are some gotchas that you should be aware of though...

In the example above, if you were to replace the value of this.data completely, then your collectionObserver will not work, unless you subscribe again.

If you are always going to replace your array data, then the @observable would work at this point.

As an example, check out this gist.run.

Here is the code for reference:

1import {BindingEngine, inject, observable} from 'aurelia-framework'
2
3@inject(BindingEngine)
4export class App {
5 @observable data2 = []
6
7 constructor(bindingEngine) {
8 this.bindingEngine = bindingEngine
9 this.data = []
10 this.log = []
11 }
12
13 attached() {
14 this.observeData()
15 }
16
17 observeData() {
18 if (this.subscription) {
19 this.subscription.dispose()
20 }
21 this.subscription = this.bindingEngine
22 .collectionObserver(this.data)
23 .subscribe(splices => {
24 this.dataChanged(splices)
25 })
26 }
27
28 detached() {
29 if (this.subscription) {
30 this.subscription.dispose()
31 }
32 }
33
34 dataChanged(splices) {
35 console.debug('dataChanged', splices)
36 this.log.unshift('data changed ' + new Date())
37 }
38
39 data2Changed(newVal) {
40 console.debug('data2Changed', newVal)
41 this.log.unshift('data2 changed ' + new Date())
42 }
43
44 addData() {
45 this.data.push(new Date())
46 this.data2.push(new Date())
47 }
48
49 popData() {
50 this.data.pop()
51 this.data2.pop()
52 }
53
54 spliceData() {
55 const rand = Math.floor(Math.random() * this.data.length)
56 this.data.splice(rand, 1, 'spliced')
57 this.data2.splice(rand, 1, 'spliced')
58 }
59
60 replaceData() {
61 this.data = ['replaced', 'data', 'completely']
62 this.data2 = ['replaced', 'data', 'completely']
63 }
64}

You will notice that anytime we are modifying the array of data (if you click the Add Data, Pop Data, or Splice Data buttons) the dataChanged() function is triggered. The observable data2 variable is not. If you press the Replace Data button you will see that the data2Changed() function is triggered, and the dataChange() function is no longer triggered on the data array changing.

So you may have to come up with a combination of solutions if you want to observe both the array being replaced and the array being modified. Something like this:

1import {BindingEngine, inject, observable} from 'aurelia-framework'
2
3@inject(BindingEngine)
4export class App {
5 @observable data = []
6
7 constructor(bindingEngine) {
8 this.bindingEngine = bindingEngine
9 this.log = []
10 }
11
12 attached() {
13 this.observeData()
14 }
15
16 observeData() {
17 if (this.subscription) {
18 this.subscription.dispose()
19 }
20 this.subscription = this.bindingEngine
21 .collectionObserver(this.data)
22 .subscribe(splices => {
23 this.dataModified(splices)
24 })
25 }
26
27 detached() {
28 if (this.subscription) {
29 this.subscription.dispose()
30 }
31 }
32
33 dataChanged(newVal) {
34 this.log.unshift('data changed ' + new Date())
35 this.observeData()
36 }
37
38 dataModified(splices) {
39 this.log.unshift('data modified ' + new Date())
40 }
41}

See an example running here.

Discuss on TwitterEdit post on GitHub

Share article
Dustin Davis

Dustin Davis is a software engineer, people manager, hacker, and entreprenuer. He loves to develop systems and automation. He lives with his wife and five kids in Utah.

Join the Newsletter



Dustin Davis