Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting parent route in EmberJS

Tags:

ember.js

I'm making a reusable (sort of polymorphic) comments widget. I want a button that enables me to go back to the parent route (e.g., if I'm at /blog_posts/1/comments, I want the button to take me back to /blog_posts/1).

I'm currently using transitionToRoute('blog_post'), but this won't work in the long run because I want this code to generically run with any model (i.e. it won't know anything about the route's name, so I can't call 'blog_post'). I guess I'm looking for either something like Rails' url_for, or a way of saying router.get('parent_route') (or controller.get('parent_route')).

Any pointers or ideas? Thanks.

like image 774
iHiD Avatar asked Apr 08 '13 02:04

iHiD


2 Answers

This was answered in the year 2013 for ember v0.9.8 or something, the framework has come a long way since then. I think there might be a much better solution with the current version of the framework. Since, I'm not in touch with Ember, can't really update this answer!

Inspired from a private function in the source code, Add the following method to the Routes which returns the name of the parentRoute

Ember.Route.reopen({
  getParentRoute: function(){
    var route = this;
    var handlerInfos = route.router.router.currentHandlerInfos;
    var parent, current;

    for (var i=0, l=handlerInfos.length; i<l; i++) {
      current = handlerInfos[i].handler;
      if((current.routeName == route.routeName)||(current.routeName.match(/./) && current.routeName.split('.')[1] == route.routeName )){
        return parent.routeName;
      }
      parent = current;
    }
  }
})

Use inside routes as follows

App.SomeRoute = Ember.Route.extend({
  events: {
    goBack: function(){
      this.transitionTo(this.getParentRoute());
    }
  }
})

Handlebars

<script type="text/x-handlebars" data-template-name="some">
  <a href="#" {{action goBack}}>Back</a>
</script>

For the actual code, open this and do a CTRL+F for function parentRoute

like image 197
Mudassir Ali Avatar answered Oct 08 '22 17:10

Mudassir Ali


You can use a generic {{action }} in your template but have the specifics of the "go back" implemented in the router. This works because Ember bubbles up the goBack event first to the controller, then the current route, then the parent route, etc, until an action handler is found. In this case, there is no matching action on the controller, so it is handled by the current route. This keeps your template/view/controller agnostic to the specifics, but when you are hooking up the widget you can specify how the "go back" should be handled.

In the example the same button causes the route to change to different routes depending on which route is the current route:

  • in route /posts the back button transitions to /
  • in route /posts/new the back button transitions to /posts

JSBin example

Javascript:

App = Ember.Application.create({});

App.Router.map(function() {
  this.resource('posts', function() {
    this.route('new');
  });
});

App.PostsRoute = Ember.Route.extend({
  events: {
    goBack: function(){
      this.transitionTo('index'); 
    }
  }
});

App.PostsNewRoute = Ember.Route.extend({
  events: {
    goBack: function(){
      this.transitionTo('posts'); 
    }
  }
});

Template:

<script type="text/x-handlebars" data-template-name="index">
  <h2>Index Content:</h2>
  {{#linkTo posts}}Posts{{/linkTo}}
  {{outlet}}
</script>

  <script type="text/x-handlebars" data-template-name="posts">
    <h2>Posts</h2>
    <button {{action goBack}}>Go back</button>
    {{#linkTo posts.new}}New{{/linkTo}}
    {{outlet}}
  </script>

  <script type="text/x-handlebars" data-template-name="posts/new">
    <h2>Posts/New</h2>
  </script>
like image 41
CraigTeegarden Avatar answered Oct 08 '22 17:10

CraigTeegarden