Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Display crumble path with ember

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:

  1. Listen on route change
  2. Finding current route
  3. displaying list of the current route
  4. display working links to the steps in the route

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:

  • When I go to the URL: #/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>
  • The URL's should be a valid route
  • The menu is now hardcoded with {{#linkTo}} to the routes, I tried to make that dynamic, like here but a transitionTo doesn't trigger the currentPath-observer

The 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.

like image 486
Willem de Wit Avatar asked Feb 28 '13 09:02

Willem de Wit


2 Answers

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.

like image 94
Wojciech Bednarski Avatar answered Sep 30 '22 16:09

Wojciech Bednarski


I came up with a much simpler solution that I posted to the Ember discourse.

like image 25
Iest Avatar answered Sep 30 '22 17:09

Iest