Did @each changed?

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…

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.

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.

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:

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

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’.

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:

It is also important to say that @each has been deprecated:

https://emberjs.com/deprecations/ember/v3.x/#toc_getting-the-each-property

Although in your original question you say something about it changing in 2.7 :thinking: I think it’s still possible (but as it’s deprecated it shouldn’t be used any more). I think it’s more likely that the .property() syntax isn’t working for you any more. You should consider upgrading to the new computed property syntax:

https://guides.emberjs.com/release/object-model/computed-properties/