Posted by Dan Freeman

Sep 25, 2014 3:21:32 PM


Over the past few months at Salsify we've spent some time exploring Ember.js and incorporating it into parts of our front-end. There's a lot to say on the topic, but today we'll just be taking a look at one of our first forays outside of the land of Ember's baked-in pieces: automatically generating breadcrumbs based on a user's application state.

Breadcrumbs are a common navigational aid in web apps. They provide a user both with a means of getting their bearings, as well as a way to quickly jump to a higher point in the application's navigational hierarchy. To implement useful crumbs, though, either every page must manually have the appropriate crumbs inserted, or the application code needs to have a deep knowledge of its own structure and where each page fits into it. Enter Ember's routes.

Routes provide the core structure of any Ember application. They can be nested under one another, and it's easy to jump from one point in the route tree to another just by knowing the name of the route you'd like to transition to. To facilitate this, Ember maintains a wealth of information about what routes are currently active and how those routes are tied to the other pieces of the application.

Consider, for example, an application that deals with quintessentially-generic "items". The main route in the app might display a list of items in the system, and from there you might be able to click to see details about a specific item, and then you might be able to click to go edit that item. One simple route hierarchy for that setup would look like this, with the corresponding URL paths:

  • items: /items
    • item: /items/{item-id}
      • item.edit: /items/{item-id}/edit

A reasonable set of breadcrumbs for these routes arises fairly naturally. When editing a particular item, you could imagine wanting to return to the detail view for that item, or go all the way back to the list of all items. The crumbs might look something like this:

    Items > {item-name} > Edit

Each item in the trail corresponds to one route in the hierarchy, and each of those routes has a corresponding controller whose job it is to hold on to information for its route and expose that information in a useful way to the UI. It makes sense, then, for each controller to expose the label for its crumb. The items route's controller, for instance, might look like this:

The edit route's label would be similarly defined. For the item route, though, we'd like to base the label on the item's name rather than using static text. Fortunately Ember's computed properties make this simple:

We've got the labels for our crumbs all laid out, but now we need a way to tie it all together. This is where Ember's deep understanding of the active route hierarchy comes into play.

With this controller, we can expose every route with a defined breadcrumb label to a small template that will produce a link to each of those routes.

As it stands, we can exclude any route from the trail by not defining a breadcrumbName on its controller. You could also imagine allowing routes to define a custom destination for their crumb, or otherwise tweaking its behavior, using the patterns established here. You can see a full working demo of the setup we just walked through below. 

Working Breadcrumbs Example

Have you implemented a similar solution for handling breadcrumbs? Or come up with something else entirely? Leave a comment; we'd love to hear about it.


Topics: Engineering

comments powered by Disqus