How to get the path of an object from the template?


#1

Based on the StackOverflow question here: http://stackoverflow.com/questions/38221230/how-to-update-nested-object-in-ember

Basically, our (new) project isn’t easily adaptable to Ember’s Models (from what we can gather). It seems like it would be a lot easier to store our data on an Observable object that we then inject wherever needed.

The problem is that Ember doesn’t detect updates to our data when it changes due to user input. The example in the SO question shows that we can’t simply set the data, because we don’t know the precise path from the service to the nested object that we want to update.

Would it be crazy to suggest making the path available to the action callbacks? I know of a similar library (Ractive) that makes the path (keypath) available on all events: http://docs.ractivejs.org/latest/proxy-events


#2

I provide a twiddle here


#3

OK, thanks.

I figured out that the use of Ember.A is not necessary - you can use a native array (so long as prototype extensions are allowed). But why is there no prototype extension for native objects?

Second question, I tried to use Ember.Object instead of arrays…but that doesn’t work either. Is Object not Observable?


#4

First question I don’t know why.

Second question I wondered what is your data structure?

Object is observable, but you need to set any property of object exactly. I mean your key value (properties) should has a predefined names


#5

I tried a trick wherein I take my native java object, and pass it as an argument to Ember.Object.create(). Here’s my code:

    fix(obj) {
        if(obj === null || typeof(obj) !== 'object') {
            // Not an object, so just return it as-is
            return obj;
        }
        
        // Just grab the own properties of the given object
        var newObj = {};
        
        for(var prop in obj) {
            if(!obj.hasOwnProperty(prop)) {
                continue;
            }
            
            newObj[prop] = this.fix(obj[prop]);
        }
        
        // Now, convert to an Ember object
        return Ember.Object.create(
            newObj
        );
    }

Actually the code should dig into Arrays, but for my toy example I just have objects. But this doesn’t work either. Nor does it work if I make newObj an empty Ember.Object and set the properties using newObj.set(prop, this.fix(obj[prop])).


#6

OK, this is driving me up the wall…

I figured that I must have misunderstood your comment. When you said “predefined”, I guess you meant that I have to extend Object and tell it what properties I need, not just create new ones with dynamic properties. So, I tried the following:

const Crit = Ember.Object.extend({
    data1: null,
    data2: null
})

const Crits = Ember.Object.extend({
    crit1: null,
    crit2: null
});

Then when I load them:

    loadCrits() {
        var c1 = Crit.create({data1: "zero", data2: "one"});
        var c2 = Crit.create({data1: "two", data2: "three"});
        var crits = Crits.create({crit1: c1, crit2: c2});
        this.set("crits", crits);
    }

But this doesn’t work either! Any idea what I’m missing?


#7

I created a Twiddle to show it: https://ember-twiddle.com/2150099882893760cef237ff2bd22e85

Basically, the critService is used by two (nearly identical) Components. The Crits are Ember objects. The “change” button doesn’t work - it changes the value, but the view does not update.

Any idea why this wouldn’t work?


#8

An answer was provided here: http://stackoverflow.com/questions/38302396/ember-binding-on-custom-objects