How do I disambiguate nested routes in ember.js?
Asked Answered
V

3

6

I have two resources that both have the same sub-resource:

App.Router.map(function() {
  this.resource('post', function() {
    this.resource('comments', function() {
      this.route('new');
    });
  });

  this.resource('product', function() {
    this.resource('comments', function() {
      this.route('new');
    });
  });
});

The problem is that the ember router builds the names of the route objects out of just the current and parent routes, not out of the whole hierarchy. Thus, it tries to route both /posts/:id/comments/new and /products/:id/comments/new to the App.NewCommentRoute object. What can I do to fix this?

This post was adapted from a GitHub issue.

Violaceous answered 17/2, 2013 at 17:36 Comment(3)
This was originally my question: github.com/emberjs/ember.js/issues/2086 Feels a little like my rep is being poached.Reannareap
Sorry about that. I didn't see it. I'll mark my answer as community wiki. (Questions can't be, though I did link to your GitHub issue in the question text.)Violaceous
Thanks. Your answer is all yours, though, so you should be getting all the rep for it. Only the original question was mine.Reannareap
R
6

I took James A. Rosen's solution one step further and it worked like a charm. A bit redundant, but makes things much more intuitive down the road:

App.Router.map(function() {
  this.resource('post', function() {
    this.resource('post.comments', { path: '/comments' }, function() {
      this.route('new');
    });
  });

  this.resource('product', function() {
    this.resource('product.comments', { path: '/comments' }, function() {
      this.route('new');
    });
  });
});

This now allows you to use transitionTo('product.comments.new') or App.register('route:product.comments.new', myRouteHandler) just as originally expected.

If you don't manually register your route handler, Ember, gracefully, will even look for it in App.ProductCommentsNewRoute

The only downside is the redundancy of defining the name of the sub-resource with the same root name that the parent resource already has.

Reannareap answered 18/2, 2013 at 22:0 Comment(0)
V
4

When you specify a route, the path defaults to the name of the route, but you can override that behavior. You can disambiguate deeply-nested routes by adding more information to the name. There are two ways to achieve essentially the same outcome:

App.Router.map(function() {
  this.resource('post', function() {
    this.resource('postComments', { path: '/comments' }, function() {
      this.route('new');
    });
  });

  this.resource('product', function() {
    this.resource('productComments', { path: '/comments' }, function() {
      this.route('new');
    });
  });
});
App.Router.map(function() {
  this.resource('post', function() {
    this.resource('comments', function() {
      this.route('newPost', { path: '/new' });
    });
  });

  this.resource('product', function() {
    this.resource('comments', function() {
      this.route('newPost', { path: '/new' });
    });
  });
});

In both cases, the router will now look for App.NewPostCommentsPath and App.NewProductCommentsPath. The advantage of the first over the second is that if you want to refer to the routes externally, they look like "postComments.new" instead of "comments.newPost". The former reads better to me.

Violaceous answered 17/2, 2013 at 17:36 Comment(1)
+1 Thanks for this. This is an effective workaround. Though, as mentioned in the original thread on GitHub, it's not really a proper solution that the Ember team should be satisfied with.Reannareap
C
1

As two years has passed, Ember has improved a lot.

Since Ember 1.7, routes can also has subroutes: http://emberjs.com/blog/2014/08/23/ember-1-7-0-released.html#toc_new-features.

So we can rewrite this as:

this.route('post', function() {
    this.route('comments', { path: '/comments' }, function() {
        this.route('new');
    });
});

this.route('product', function() {
    this.route('comments', { path: '/comments' }, function() {
        this.route('new');
    });
});
Caitiff answered 4/3, 2015 at 14:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.