Ember.js: Loading Similar Models Directly

I don't understand how ember loads related models.

Let's say my model is:

export default DS.Model.extend({
  title: DS.attr('string'),
  description: DS.attr('string'),
  states: DS.hasMany('state', {async: true})
})

      

I am loading this on my external routes. When navigating with ember-app (into nested routes), model contexts are often used for routes, rather than using a route model hook, but using a helper link (when using dynamic segments, the hook model will be ignored). When the target route has something in its template, for example {{#each model.states as |state|}}

, ember will automatically load the appropriate model-records from (in this case) the state model. (How and why?) Only because of the each

template?

When directly accessing a dynamic route, the model is not specified and the hook of the dynamic route model will be invoked. So loading my model is easy: just override the model hook and load the entry with url ( return this.store.find('item', {title: params.item_title})

) parameter . But no linked models will be loaded. How can I do it manually and what (and when) is the way that ember works by default?

+3


source to share


1 answer


How does Ember know how to get relationships automatically?

ember-data allows you to define relationships (currently only belongsTo

and hasMany

) with the option async

set to true

or false

. Based on this parameter, after retrieving the model from the API (using the method find

), the ember data will expect the relationship to be either directly in the JSON response or not. You have async: true

(which is a fairly common and supported way of handling relationships), so the ember data assumes that in your JSON response it is receiving id

states, but not necessarily the states themselves.

If you define yours hasMany

as async: true

, it always returns a promise. This means that if you do something like this:

this.get("item").get("states")[0] 

      

Will not work as get("states")

it will not return an array, but promises to retrieve that array. However, Handlebars are smart (like methods get

and set

Ember) and it can find out what the promise is and wait for it to resolve before using it. Therefore, if your template contains:

{{#each model.states as |state|}}

      

Handlebars will know what states

a promise is, wait for it to resolve, and once resolved, they use its contents as an array. Very similar behavior can be found with the method belongsTo

. Assuming yours item

has one state

, if you use the code like this:

this.get("item.state.somePropertyOfState")

      



Even if you didn't choose state

and currently don't know what the value is somePropertyOfState

, ember will get

detect that promise and automatically select it for you.

How do I manually select a relationship?

There are several ways to do this.

First, you need to explicitly enter them into the ember code:

this.get("item.states").then(function(states) {
  # now you have fetched the states that the item has, and moreover
  # they are accessible in states variable
});

      

Second, you can let Ember do this automatically for you, as I described earlier (via a template, for example).

Third, you can send relationships with your response using a mechanism called sideload. This will significantly reduce the number of API requests. When you allow ember to fetch your relationship, ember makes one request per relationship object, which means if you have ten states

owned item

, the API will hit ten times. However, if you disable states

when fetching item

, the request will only be sent once. Take a look here for more information on this.

Sorry for the long post, but I hope I covered a little.

+9


source







All Articles