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.
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
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:
/posts
the back button transitions to /
/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>
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