{{Quest 2}}: How to load multiple models on the same route?

3 min read • 2nd June 2018
Loading multiple models on the same route image

Link to this sectionLevel: Intermediate

Supposing that you would need to load multiple data required for a page that is served by different API endpoints, then how do you approach fetching that data in the Ember route's model hook?

For example, you have a form that requires meta information about countries while there is also a new form model that needs to be created while navigating to that route, now, we have 2 models — country and form. In order for the form to render the countries, let's assume you are required to fetch that in the route. How do you go about it? Let's see.


EmberJS: How to load multiple models on the same route?

You want to be careful about whether or not returning multiple models in your model hook is appropriate. Ask yourself this simple question:

Does my route load dynamic data based on the url using a slug :id? i.e. this.resource('user-form', { path: ':id' });

Link to this sectionIf you answered yes

Do not attempt to load multiple models from the model hook in that route!!! The reason lies in the way Ember handles linking to routes. If you provide a model when linking to that route either using link-to or using transitionTo('user-form.edit', model), it will skip the model hook and use the supplied model. This is probably problematic since you expected multiple models, but only one model would be delivered. Here's an alternative:

Link to this sectionDo it in afterModel

If you need it to block the transition (like the model hook does) return a promise from the afterModel hook. You will need to manually keep track of the results from that hook and hook them up to your controller.

import Route from '@ember/routing/route';
import { get, set } from '@ember/object';

export default Route.extend({
  model(params) {
    return this.store.createRecord('user-form');
  },

  afterModel() {
    return this.store.findAll('country').then((countries) => {
      this.countries = countries;
    });
  },

  setupController(controller, model) {
    this._super(controller, model);

    set(controller, 'countries', get(this, 'countries'));
  }
});

Link to this sectionIf you answered no

Go ahead and return multiple models from the route's model hook. You could use any combination inside the hash as RSVP will resolve the model hook only when all the objects are resolved.

import Route from '@ember/routing/route';
import RSVP from 'rsvp';

export default Route.extend({
  model() {
    return RSVP.hash({
      form: this.store.createRecord('user-form'),
      countries: this.store.findAll('country')
    };
  }
});

Note
This is a minor modification of what was posted on the same SO post and due credits to kingpin2k for posting such an elaborate answer.

Enjoyed this article? Tweet it.

I guess you might be looking to add your comments? Glad to tell you that this section is under construction. But don't hold on to your thoughts! DM them to me on Twitter