How can I share templates, controllers, and routes between parent routes?

I would like to share templates, controllers, and routes between different parent routes. For example, I’d like to use the same leaf templates (billing.hbs and subscriptions.hbs) under admin.user.billing and user.billing.

For admins

this.route('admin', { path: '/admin' }, function () {
    this.route('user', { path: '/user/:user_id' }, function () {
        this.route('billing', { path: '/billing' });
        this.route('subscriptions', { path: '/subscriptions' });
    });
    this.route('other', { path: '/other' });
});

For users

this.route('user', { path: '' }, function () {
    this.route('billing', { path: '/billing' });
    this.route('subscriptions', { path: '/subscriptions' });
});

How about using router#render to explicitly assign the template / controller ? Ref: Route - 4.6 - Ember API Documentation I think route can not be shared in this way though.

you can use components for this…

1 Like

I am already using components, but I don’t see how using components can alleviate the need for two templates and two routers for every endpoint I want to share between the admin and user routes.

Both the controller type and template backing a route is configurable.

I was trying to figure out how to call route#render, but it seems like defining a custom templateName would be even easier.

It looks like I can just specify an arbitrary template using the path from app/templates/. Thanks!

Yeah, for example if your template was stored in app/templates/foo/bar.hbs your templateName would be foo/bar

For anyone who encounters this thread, this is the solution I went with:

router.js

function userRoutes() {
    this.route('foo', { path: '/foo' });
}

Router.map(function () {
    this.route('admin', { path: '/admin' }, function () {
        this.route('user', { path: '/user/:user_id' }, userRoutes);
    });
    this.route('user', { path: '' }, userRoutes);
});

templates/user/foo.hbs

{{user-foo}} {{!-- component shim --}}

routes/user/foo.js

export default Ember.Route.extend({
    // the only tricky part here is determining what param to pass to modelFor
    // (admin.user or user) when we need the parent's model
});

routes/admin/user/foo.js

import UserFoo from '../../user/foo';
export default UserFoo.extend({
    templateName: 'user/foo',
});

I still need one extra route file per route, but everything else is shared. I added a service (Context) that is aware of whether we’re in the user or admin context based on whether we’re in the admin.user or user route, and a custom link-to helper that uses the correct route when creating links.

if it is same content why put it in differents path?

I wondering ou should use same route since it does same thing.

The admin/user/:user_id route & template behave differently than the user route & template. They pull a different user (one from session, one from the url path) and display very different information. It’s really only their outlets that are similar.