How can a child route (or resource) access a parent resource's model from within the model hook?
Asked Answered
N

2

11

Seems like in the case of nested routes, each route's model hook is called before any of the setupController hooks are called. So how can a child route safely access the parent's model?

In my case, the models aren't actually persisting entities. They're both generated, based on the params, in the model hooks. So I wouldn't think a Parent.find() / ajax / promise seems like the way to go. Ideally, the parent model should be accessible through the ParentController, no? Or is this approach not in keeping with best practices?

App.Router.map(function() {
  this.resource("parent", { path: "parent/:name" }, function() {
    this.route('child');
  });
});

App.ParentRoute = Ember.Route.extend({
  model: function(params) {
    // build a model here, based on params.
    // no asynch stuff happening, should be good to go.
    return { lastName: params.name }
  },

  setupController(controller, model) {
    controller.set('model', model);
  }
});

App.ChildRoute = Ember.Route.extend({
  model: function(params) {
    parentModel = this.controllerFor('parent').get('model');
    return {lastName: parentModel.get('name') + 'son' };

    // parent Model is null
    // need the parent model HERE, 
    // but I can't get it through the controller yet
    // as setupController in the parent route hasn't been called yet
  }
});
Nablus answered 7/9, 2013 at 2:16 Comment(0)
N
28

modelFor

How'd I miss that?

App.ChildRoute = Ember.Route.extend({
  model: function(params) {
    parentModel = this.modelFor('parent');
    return {lastName: parentModel.get('name') + 'son' };
  }
});
Nablus answered 7/9, 2013 at 2:30 Comment(4)
Gotta love it when you can answer your own question.Gramnegative
Thanks @doublea. I'd like to further clarify that the argument you pass to modelFor is the name of the parent route whose model you would like. E.g. user, user.posts, etc. And here are the docs.Codeine
Thank you so much @steve.hanson, I was doing it with upper camel case, and not with dot notation!!Bootlace
In my case, the modelFor approach only worked when I specified the route whose model I wanted, like let account = this.modelFor('admin.accounts.edit');Chumash
O
1

doublea's answer still applies for Ember 3.x, with some slight changes to the boilerplate syntax of the route. Also the get is no longer necessary, but doesn't hurt anything to leave it there. Here's the 3.x syntax:

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

export default Route.extend({
    model(params) {
       parentModel = this.modelFor('parent');
       return {lastName: parentModel.name + 'son' };
    }
});

For Ember 2.16 through at least all of Ember 3, another way to get information about parent routes is using the RouterService

Methods like currentRouteName and currentUrl can be helpful for display, although it's best to avoid fancy string parsing when there are better options. You can also use the router service's transitionTo in order to change routes from a Component.

The Router Service can be used like this:

import {inject as service} from '@ember/service';

export default Component.extend({
    router: service(),
    actions: {
      clickedAThing() {
        this.router.transitionTo('some.route')
      }
    }
})
Oilbird answered 19/8, 2018 at 20:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.