I have a computed property on an ObjectController, which depends on a computed property itself and watches the number of elements in the underlying array. The problem is that the computed property updates if the number of elements changes but does not recomputed if the contents of an element changes.
newSnakeMorph: function() {
if (this.get('model.newSnakeGenes').get('length') > 0)
{
var genes = this.get('model.newSnakeGenes');
var Result = "";
for (var Index in genes)
{
if (isNumber(Index)) // Leaking properties bug
{
Result += genes[Index].get('morph') + " ";
}
}
return Result;
}
else
{
return "Normal";
}
}.property('model.newSnakeGenes.[]'),
How to I alter the observer â,property(âmodel.newSnakeGenes.â)â to observe changes within the elements stored in the array?
Well I thought of a very hackish way to do it and tested it and it works. Not sure itâs the best thing to do but itâs all I can figure out. Would love to find the Ember right way to do this.
In the code below I create a fake object and add and remove it from the array so the length will change (temporarily, at least) and cause the computed properties to recompute. I can do this because in the controller I know I have changed the contents of one of the items in the array (as shown below).
var genes = this.get('model.newSnakeGenes');
for (var index in genes)
{
// Ember bug #5501
if (isNumber(index))
{
if (genes[index].get('complex') == gene.get('complex'))
{
if (genes[index].get('allele2') == "Normal")
{
genes[index].set('allele2', gene.get('name'));
// Hackish way to cause computed properties to recompute
var Fake = App.Locus.create({id: 'fake'});
genes.pushObject(Fake);
genes.removeObject(Fake);
return;
}
else
{
alert("This complex (" + gene.complex + ") already has the maximum number of genes.");
return;
}
}
}
}
A lot of things in Ember donât actually exist until they are observed, including computer properties- they only calculate when youâre actually calling them. If you have chains of these, they arenât always calling the most current version. Try running Ember.run.sync(); after you set the value.
As I understand Ember Docs the array.[] notation tells Ember to watch for Array manipulation - so push & remove are observed, whereas array.@each tells Ember to not only watch for Array manipulation but for manipulation of the Array values too, which seems to be the solution to your problem. So, instead of
Thank you all for your responses. Yes, @each is not sufficient to watch element count change and element detail change. But @each.something does watch both, as I am using:
}.property('model.newSnakeGenes.@each.allele2'),
and it works great. The only property of an existing âgeneâ that can change is the second allele so this watches that property and does also seem to get element change when new âgenesâ (an additional Locus object) are added to the array.