Giving {{render}} context with only a model ID?


#1

Is there a canonical way to render a model using {{render}} but only being able to provide the ID of the model you want to “contextualize”? I considered modifying the ‘render’ handler declaration or making one of my own, but that is starting to look a bit hairy and I figured I’d look for something better. I feel like this may be a simple problem that I am overlooking, but can’t find a solution to.

Thanks :smile:


#2

It seems to me that the question the you are asking is not your real problem but rather a problem you encountered while working out a solution for your initial problem =)

May I ask what it is you are trying to do ?


#3

I have Object A which has an array of IDs of other objects that will be loaded alongside it, visually. They have their own template that I want to render, but only have the ID and want to load the data for the object based on that.

Also it might be worth noting that I am not using Ember Data. Would that help, with the whole hasMany relationship model?


#4

You don’t really need to use ember-data for this. However you mind find inspiration in how things work there.

Ember data uses PromiseObjects. these are promise that resolve to an object and behave like an object Proxy when the object is available. now, I don’t know how you load your data from the id but let’s pretend you do something like this

fetchObjectFromTheInternet(id).then(function (object) {
  // object is loaded
});

I’m assuming you are using promise to leverage asynchrony. If not, you should look into it.

a PromiseObject in ember-data is defined like this

DS.PromiseObject = Ember.ObjectProxy.extend(Ember.PromiseProxyMixin);

So it’s definitely not something difficult. You can use a PromiseObject like this

var objectInTheFuture = PromiseObject.create({ promise: fetchObjectFromTheInternet(id) });

Now you can set up your objectInTheFuture on your controller and your view and use it in your template as if it were already loaded, with additionnal loading info on the isPending attribute

Since you have several IDs you can always map your array of ids to an array of PromiseObjects

var myObjects = myIds.map(function (id) {
  return fetchObjectFromTheInternet(id);
});

and use them in a template like this

{{#each myObjects}}
  {{id}}
  {{value}}
  {{whateverElseIsInThere}}
{{/each}}

or if you really want a render helper

{{#each myObjects}}
  {{render this}}
{{/each}}

Hope that helps.


#5

I am using promises, but the problem is less fetching things asynchronously, and more my understanding of at what point I can embed things, and if I have to at all.

I guess what I mean is, at what point would I load myObjects? They are not initially embedded in the first object, and I only want to load them when they’re visually needed.

I guess an example would be a good idea.

So, say I have my array of users:

[
    {
        id: 0,
        someOtherJunk: "blah",
        child: 1
    }
]

Even if the object has only one reference to another object;

Let’s say I go to /user/0 and it is set up to return exactly what I have up there. My template looks something like this:

{{id}}
{{someOtherJunk}}
This item's child:
{{render child}}

How would I get that render statement to work? Where could I load in child as an object? I can’t just infinitely load all things linked to it, as it’s all shaped like a rather expansive graph. I am only interested in loading nearest neighbours.

I could obviously create another field in the first object called itemObj or something like that and stick the actual, loaded object in there, but how would I trigger it to load?

Would an elegant solution be to, on load, change all references in the object to functions, which would act as promises, and when called by something in the template load the object for you?

As for promises, I currently have App.Item.find() doing that.

This is why my initial idea of overriding the {{render}} helper and integrating asynchronous loading directly into it came into play.