Why does Ember Router only allow navigating to leaf routes?
Asked Answered
E

2

6

Something I have noticed recently with Ember Router is it only allows navigating to leaf routes — routes without child routes.

Now unless I'm doing things incorrectly then this seems like a bug/mistake in design.

Let's take for example something like this:

I have a collection of projects, each project has many collaborators, with this I want to build a UI with a 3 column layout (something like your standard desktop email client) where on the left I have a list of projects, when clicking on a project the middle column shows a list of collaborators, and clicking on a collaborator loads its details into the righthand column.

Now with the routing I want to navigate to /projects/1 when clicking on a project and onto /projects/1/collaborators/23 when clicking on a collaborator.

Here is a router illustrating the first part of nested route:

App.reopen(
  Router: Ember.Router.extend(
    enableLogging: true
    location: 'hash'

    root: Ember.Route.extend(
      index: Ember.Route.extend(
        route: '/'

        redirectsTo: 'projects'
      )

      projects: Ember.Route.extend(
        # This route is not routable because it is not a leaf route.
        route: '/projects'

        connectOutlets: (router) ->
          # List projects in left column
          router.get('applicationController').connectOutlet('projects', App.projects)

        show: Ember.Route.extend(
          # This route is routable because it is a leaf route.
          route: '/:project_id'

          connectOutlets: (router, project) ->
            # Render the project into the second column, which actually renders
            # a list of collaborators.
            router.get('projectsController').connectOutlet('project', project)
        )
      )
    )
  )
)

As you'll see Ember doesn't call updateRoute (set the URL) until transitioning to root.projects.show because of this line https://github.com/emberjs/ember.js/blob/master/packages/ember-routing/lib/routable.js#L81

Has anyone else done anything like this? Is there a better way to design this?

Episodic answered 8/7, 2012 at 3:5 Comment(0)
G
7

The best way I've found to do this is to have a root.projects.index state with a route of "/" and nothing else. This way every page has it's own specific state.

projects: Ember.Route.extend(
  # This route is not routable because it is not a leaf route.
  route: '/projects'

  connectOutlets: (router) ->
    # List projects in left column
    router.get('applicationController').connectOutlet('projects', App.projects)

  index: Ember.Route.extend(
    route: "/"
  )

  show: Ember.Route.extend(
    # This route is routable because it is a leaf route.
    route: '/:project_id'

    connectOutlets: (router, project) ->
      # Render the project into the second column, which actually renders
      # a list of collaborators.
      router.get('projectsController').connectOutlet('project', project)
  )
)

N.B. That being said I'm doing a similar thing with a 3 column layout, and am matching the middle and right column to the routes as above and adding the left column in a shared layout to each of the possible middle views.

Girvin answered 8/7, 2012 at 6:57 Comment(1)
@BradleyPriest I have a question about this. I am finding it difficult to understand how to use Ember.Router with CRUD scenarios. Could you take a look?Feuchtwanger
L
2

I think this issue is resolved. I am using ember routes without an index and do not face any leaf state issues. I was browsing why we need an index at all and I landed up here. Is there any other reason for using the index state too?

Lynching answered 3/10, 2012 at 9:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.