Hacking array proxy to observe changes on nested array

Published on April 23, 2015 by Toran Billups

Just today I found myself asking why a rendered list in my template can't observe changes when the underlying model has an array and I decide to watch for changes to that nested array. If that sounds fun checkout the issue from 2012 for more details but the TL;DR is that doing a complex computed property (like you see below) isn't supported.

My example was slightly more complex than just a computed so I thought to write up a quick "how-to" and share a few jsbin examples. First I'll show the not working example to express what I'd like to see happen (but sadly isn't supported today).

Here is the full (broken example) jsbin if you want to see it in action. In the example I have an array of models but I've decided only to show items that have the number 8 inside a nested array called things. I then implemented a controller action that removes this number from the things array to ensure the view would update itself (removing the model from the template).

Instead in this example you will see that this doesn't happen ...so what other options do you have? I found a few looking around on github today but my friend Brandon Williams came up with a killer hack that I just had to blog about because it seemed to solve the issue (aka- the view now updates).

Here is the working jsbin to see it in action. The workaround starts by coming to terms with the idea that I can't listen on a 2nd @each. So instead I create a count computed on the model itself that will listen to changes on the things array. I then update the ArrayProxy to listen for changes to that count property "source.@each.totalThings". Next I added a helper that allows the model itself to remove that number 8 from the nested things array (instead of doing the removeObject inside the controller action directly). And finally this does require totalThings to be in the template to force the getter (if you don't need that number showing up you could always hide the div/span/etc)

Clearly a hack but the simplest I've seen yet that allows the template to observe changes on a nested array!