I want to display a crumble path with Ember. How can I iterate through the current path?
In my opinion there are two approaches:
The ember-way
EDIT: see my answer below
I keep this question up-to-date with the current status of displaying breadcrumbs. You can browse through the revisions of this question to see the history.
There are a couple of goals here:
Controller
App.ApplicationController = Ember.Controller.extend({
needs: ['breadcrumbs'],
currentPathDidChange: function() {
path = this.get('currentPath');
console.log('path changed to: ', path);
this.get('controllers.breadcrumbs').set('content',this.get('target.router.currentHandlerInfos'));
}.observes('currentPath')
});
App.BreadcrumbsController = Em.ArrayController.extend({});
Router
App.ApplicationRoute = Ember.Route.extend({
renderTemplate: function() {
this.render();
this.render('breadcrumbs', {
outlet: 'breadcrumbs',
into: 'application',
controller: this.controllerFor('breadcrumbs')
});
}
});
Template
{{! application template }}
<div class="clearfix" id="content">
{{outlet "breadcrumbs"}}
{{outlet}}
</div>
{{! breadcrumbs template }}
<ul class="breadcrumb">
{{#each link in content}}
<li>
<a {{bindAttr href="link.name"}}>{{link.name}}</a> <span class="divider">/</span>
</li>
{{/each}}
</ul>
The current problems to tackle are:
#/websites/8/pages/1
the output for the breadcrumbs is: (I removed all the script-tag placeholders<ul class="breadcrumb">
<li>
<a href="application" data-bindattr-34="34">application</a> <span class="divider">/</span></li>
<li>
<a href="sites" data-bindattr-35="35">sites</a> <span class="divider">/</span>
</li>
<li>
<a href="site" data-bindattr-36="36">site</a> <span class="divider">/</span>
</li>
<li>
<a href="pages" data-bindattr-37="37">pages</a> <span class="divider">/</span>
</li>
<li>
<a href="page" data-bindattr-38="38">page</a> <span class="divider">/</span>
</li>
<li>
<a href="page.index" data-bindattr-39="39">page.index</a> <span class="divider">/</span>
</li>
</ul>
{{#linkTo}}
to the routes, I tried to make that dynamic, like here but a transitionTo
doesn't trigger the currentPath
-observerThe other way
Most is the same as above, but there are a couple of differences. The breadcrumbs are made by looping over location.hash
instead of getting it from the Router.
The ApplicationController becomes:
ApplicationController = Ember.Controller.extend({
needs: ['breadcrumbs'],
hashChangeOccured: function(context) {
var loc = context.split('/');
var path = [];
var prev;
loc.forEach(function(it) {
if (typeof prev === 'undefined') prev = it;
else prev += ('/'+it)
path.push(Em.Object.create({ href: prev, name: it }));
});
this.get('controllers.breadcrumbs').set('content',path)
}
});
ready : function() {
$(window).on('hashchange',function() {
Ember.Instrumentation.instrument("hash.changeOccured", location.hash);
});
$(window).trigger('hashchange');
}
We need to subscribe the custom handler in the ApplicationRoute
App.ApplicationRoute = Ember.Route.extend({
setupController: function(controller, model) {
Ember.Instrumentation.subscribe("hash.changeOccured", {
before: function(name, timestamp, payload) {
controller.send('hashChangeOccured', payload);
},
after: function() {}
});
}
});
So far the alternative approach is working best for me, but it's not a good way of doing it because when you configure your Router to use the history
instead of location.hash
this method won't work anymore.
Based on your current breadcrumb output I guess you have an error in your router.
The following command should return array with current breadcrumb:
App.get('Router.router.currentHandlerInfos');
Your router should be nested:
this.resource('page 1', function () {
this.resource('page 2');
});
You can use #linkTo
instead of a
tag in your breadcrumb, you will get active class for free.
I came up with a much simpler solution that I posted to the Ember discourse.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With