Dynamically populate models with more detailed data in emberjs

I am a bit stuck in implementing master-detail views in emberjs.

Most of my views have a master view, which is a list of names. Then the user can click on this heading and he / she will get an overlay with a detailed view (somewhat similar to a typical newsitem page).

Now I noticed that when ember requests information for the master view, it calls up URLs like: /backend/newsitems . But these challenges can become very difficult, because the backend returns a list of all the news with their details. But this seems wrong, because the user is looking only at the master view and is not yet requesting any detailed information.

Is there a way to make ember clear that a master view is needed for only a few attributes and that a request for detailed information should get additional attributes of this particular element?

As an example, my model looks like this:

 App.Newsitem = DS.Model.extend({ slug: DS.attr('string'), type: DS.attr('string'), title: DS.attr('string'), summary: DS.attr('string'), text: DS.attr('string'), thumb: DS.attr('string'), date: DS.attr('date'), mediaitems: DS.hasMany('App.Mediaitem') }); 

But for my master view, an id type title is required to display a list of titles and an icon next to that title. Then, when the user requests the details of one of them, all other attributes should be retrieved.

+7
source share
3 answers

I solved this problem if the server includes a "partial" property in the payload. "partial" will be true if it is only a partial answer, and it will be false if there is a complete answer. I also suggest a workaround if you cannot change the server API (and therefore cannot include the "partial" property in the payload).

Like others, suppose that in the hook of the route model "in detail" call the reload () method of the model if the currently loaded model is only partial:

 App.ItemRoute = Ember.Route.extend({ model: function (params) { return this.store.find('item', params.item_id).then(function (item) { if (item.get('partial')) return item.reload(); else return item; }); } }); 

This problem has been partially resolved, but if your user navigates to the main route, Ember Data will replace all fields with the server’s response and destroy any property values ​​that were not returned from the server. To overcome this, override the push store method as follows:

 App.ApplicationStore = DS.Store.extend({ push: function (type, data, _partial) { if (data.partial && this.hasRecordForId(type, data.id)) return this.getById(type, data.id); else return this._super(type, data, _partial); } }); 

This ensures that your partial payload does not overwrite the full payload.

Here's jsbin to demonstrate: http://jsbin.com/bejop/6/edit

If you cannot include a “partial” property in the answer, then you can apply the same logic as above, but look for a specific property in your model that will be displayed in your detailed answer, but not in your partial answer. Then, when you override the push method, you can do it like this:

  App.Partials = [ { type: App.Item, propertyName: 'detailed_description' } ]; App.ApplicationStore = DS.Store.extend({ push: function (type, data, _partial) { var that = this; var partial = App.Partials.find(function (p) { return p.type === that.modelFor(type); }); if (partial && !data[partial.propertyName]) return this.getById(type, data.id); return this._super(type, data, _partial); } }); 
+3
source

Is there a way to make ember clear that a master view is needed for only a few attributes and that a request for detailed information should get additional attributes of this particular element?

Of course, but maybe not the way you expect. Ember models are really lightweight, so there is no need to have a 1-1 relationship between them and your base circuit. In general, I like to think about ember models in terms of API endpoints. In this case, your API displays two different datasets, so the easiest solution is to create a separate ember model to present an easy list of names. This model will have its api endpoint in /backend/newsitem_listings .

 App.NewsitemListing = DS.Model.extend({ slug: DS.attr('string'), type: DS.attr('string'), title: DS.attr('string') }); 

Using this, you can use App.NewsitemListing.find() or App.NewsitemListing.find({query: q}) to retrieve some / all lists, then App.Newsitem.find(id) to download the details for a single entry. You might consider adding relationships to your model, such as newsitem: DS.hasOne('App.Newsitem') , or you can just use slug to generate links on the fly.

+2
source

I have had a similar problem lately and I hope that what I came up with can help you.

My API has a /books endpoint that returns an array of objects with several - but not all - fields. However, when I get GET /books/:id , I can every bit of information that is for the book with the identifier :id .

Then in Ember I have this route setting for one page of a book:

 App.BookRoute = Ember.Route.extend model: (params) -> Book.find(params.book_id) setupController: (controller, model) -> controller.set("model", model) unless model.get('full') is true model.reload().then -> # We now have all the information. # Setting `full` to `true` to prevent loading it again. model.set('full', true) return 

So, when the user just looks at the list, the model fields are mostly empty, but when she then goes to the detailed view of the book, the API is deleted and the additional data of the book is inserted into one instance of the model.

+2
source

All Articles