2

To explain my question, I have concocted a contrived example, so bear with me. I have two related ember-data models that each have the same type of embedded association:

App.Article = DS.Model.extend({
  title: DS.attr("string"),
  summary: DS.belongsTo(App.Summary, {embedded: true}),
});

App.Book = DS.Model.extend({
  title: DS.attr("string"),
  summary: DS.belongsTo(App.Summary, {embedded: true}),
});

App.Summary = DS.Model.extend({
  text: DS.attr("string"),
});

One great feature of ember-data is that find() will return an object of the correct type which can be used to render the view even before the actual data values have been retrieved from the server. However, I worry this convenience doesn't extend completely to associations.

In cases like this, when multiple types of objects share the same type of associated data, I would like to reuse my view that displays Summary objects for both Book objects and Article objects. In particular, I would like to do the following:

book: Ember.Route.extend({
  route: '/book',
  connectOutlets: function(router) {
    book = App.Book.find(1);
    router.get('applicationController').connectOutlet('titleOutlet', 'book', book);
    router.get('applicationController').connectOutlet('summaryOutlet', 'summary', book.get('summary'));
  },
}),

That is, I would like to have one view for the book-specific stuff, and one view for the summary, which is independent of whether a Book or Article is displayed.

Unfortunately, I can't do book.get('summary') because this returns null if the book has not been populated by store.load(), which is called asynchronously by Book.find().

The alternative seems to be to pass around the book object itself, and always reference nested paths, starting from the root level of the object. In this particular case, the structure of Book and Article are identical, so there is no difference. But if I want to use an association and refer to it independently of its context, it seems there should be another way.

Thoughts?

I've put together a gist illustrating this full example.

Update

I'm resigned to Mike Aski's point that this is not possible. But in order to keep my logic abstract, I create a uniformly named binding pointing to the association, where ever it may be buried, each time I connectOutlet. It's when I call connectOutlet that I know what type of object I'm sending to the controller/view and thus the view can use the binding and doesn't need to know about the rest of the object.

Bill the Lizard
  • 369,957
  • 201
  • 546
  • 842
Kevin Bullaughey
  • 2,456
  • 20
  • 35
  • I have a similar problem, but I am not sure, how to resolve it. In my case, I have settings with each Item, and settings can be a different view based on item type, so I have URL like /item/22/settings. Now I want to do `connectOutlet('settingsOutlet, item.get('settings')` in settings route (child route of 'item/:id'). Any Idea? – Nachiket Aug 28 '12 at 10:58

1 Answers1

1

You should try to pass directly the article or book instance as the summaryOutlet context, not the summary. Then, in the view, use:

{{view.content.summary.text}}

instead of what you certainly have for the moment:

{{view.content.text}}

In that way, the binding will be refreshed as soon as record data will be loaded.

I don't see any alternative: While relations are not populated in the instance, you will always get null if you try to traverse them in a synchronous, imperative maner...

Mike Aski
  • 8,960
  • 4
  • 41
  • 59
  • Yeah, I realize that would work. However it seems suboptimal because it requires the view know how to find the association inside a Book and inside an Article, which may differ. – Kevin Bullaughey Aug 07 '12 at 14:00