Did @each changed?


#1

Hi,

I’m pretty sure that in old ember (low 2.x), doing something like

function(){...}.property('arr.@each.x')

was always “stronger” than doing:

function(){...}.property('arr')

i.e with the @each dependency whenever some object was added to the array OR the array itself changed - the property would trigger its getter.

After upgrading, I noticed that defining a arr.@each.x dependency won’t trigger a property change when the array itself changes. Even worse, adding the two dependencies together doesn’t work!!!

I created some twiddles to clearify:

  1. A working example with just 'arr' - working twiddle
  2. Not working using 'arr.@each.x'- @each not working
  3. Not working even after adding back 'arr' dependency - still not working

Did anyone else noticed that? what would be the solution if I want a recalculation of the property if either the array itself changes OR something inside it?

BTW, I think this changed in Ember 2.7… but I see nothing in the release notes…


#2

UPDATE:

I now realized that the twiddle doesn’t work because my array doesn’t contains objects only… I’m sure it worked before… but it probably makes sense.


#3

I believe the .property syntax is either deprecated or will be deprecated. You may want to try using foo: computed('arr.@each.x, function(){}) etc. I could be wrong, but I think I read that somewhere.


#4

Edit: Doh, sorry, just saw your comment where you realized the problem was objects.

If you pop open dev tools on your Example number 2 I think you’ll see a steady stream of exceptions. It seems that Ember is really unhappy trying to bind arr.@each.x to a number.

Change your [i++] to [Ember.Object.create({x:i++})]; and your counter function to return this.get(‘arr.firstObject.x’); And it works.

Change it further to this: https://ember-twiddle.com/f8c125e39ba22b37184860c8cc23942e And you’ll see what @each.x is really meant for.

Note that if you want to bind to an array and only care about whether it grows, shrinks, or changes, then you want to use ‘arr.

Edit: Corrected new twiddle link


#5

Addendum - if you take your example and as the only change, alter your ‘counter’ binding from

}).property(‘arr.@each.x’), to }).property(‘arr.’),

then the example works - because it isn’t throwing an exception on @each.x and since ‘arr.’ correctly detects the replacement of ‘arr’.


#6

Right now Ember extends the function prototype itself to allow things like {}.property(‘x’). If you’re working in an environment where extending this prototype is not allowed, then you need to use Ember.computed(‘x’, function()) and turn off prototype extension: