The use case: I want the ability to construct a dynamic breadcrumb based on the current route/state hierarchy.
The problem: There is currently no public API for accessing the chain of context on the router. The internal currentHandlerInfos can be used, but not without feeling like you need to take a shower afterwards. This use case is common enough that users shouldn’t have to dig into the internal api.
Proposal: I propose we have a public API for accessing this information, but as I am not an API design expert, I am simply proposing the concept so those smarter than me can consider the issue. I’m happy to think up a variety of use cases if necessary, but the value is pretty apparent.
Some things to consider:
The user should have access to the linear hierarchy of routes &
contexts. i.e. router.get(‘currentRoutes’)
Should they be able to query for a specific route to get just that set of handler/context data for convenience?
What’s the data shape of each item in the array? Do we need all the keys found in currentHandlerInfos, or can we simply have an array of the route (‘handler’) objects?
The API is indeed lacking a clear way to do this. Maybe something just slightly cleaner would be to extend the didTransition method in your Router which receives a copy of the currentHandlerInfos list, and just maintain another property on your Router containing the list of routes. This is far from being ideal given that didTransition is private, but at least once a clean solution comes up you can turn that property into a computed property that will map to the right thing.
Following @pjlammertyn’s lead, and taking bits and bobs from variousanswers, I recently used the following:
App.ApplicationController = Ember.Controller.extend({
breadcrumbs: [],
watchCurrentPath: function () {
this.send('setCrumbs');
}.observes('currentPath'),
actions: {
currentPathDidChange: function () {
this.send('setCrumbs');
},
setCrumbs: function() {
// BEWARE:
// This is some super hacky, non-public API shit right here
var crumbs = [];
// Clear out the current crumbs
this.get('breadcrumbs').clear();
// Get all the route objects
var routes = this.container.lookup('router:main')
.get('router.currentHandlerInfos');
// Get the route name, and model if it has one
routes.forEach(function(route, i, arr) {
// Ignore index routes etc.
var name = route.name;
if (name.indexOf('.index') !== -1 || name === 'application') {
return;
}
var crumb = Ember.Object.create({
route: route.handler.routeName,
name: route.handler.routeName,
model: null
});
// If it's dynamic, you need to push in the model so we can pull out an ID in the link-to
if (route.isDynamic) {
crumb.setProperties({
model: route.handler.context,
name: route.handler.context.get('name')
});
}
// Now push it to the crumbs array
crumbs.pushObject(crumb);
});
this.set('breadcrumbs', crumbs);
// Set the last item in the breadcrumb to be active
this.get('breadcrumbs.lastObject')
.set('active', true);
}
}
});