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?

sly7_7
  • 11,961
  • 3
  • 40
  • 54
Ivan
  • 1,090
  • 1
  • 11
  • 17

2 Answers2

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.

Bradley Priest
  • 7,438
  • 1
  • 29
  • 33
  • @BradleyPriest I have a [question](http://stackoverflow.com/questions/11377498/ember-js-crud-scenarios-specifying-view-from-within-a-route) about this. I am finding it difficult to understand how to use Ember.Router with CRUD scenarios. Could you take a look? – MilkyWayJoe Jul 08 '12 at 11:22
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?

inertia
  • 404
  • 4
  • 15