我正在制作一个可重用的(多态)评论小部件。我想要一个按钮,让我回到父路线(例如,如果我在/ blog_posts / 1 / comments,我想按钮将我带回/ blog_posts / 1)。
我目前正在使用transitionToRoute('blog_post')
,但从长远来看这不会起作用,因为我希望这个代码一般可以运行任何模型(也就是说它不知道路线的名字,所以我无法调用'blog_post')。我想我正在寻找像Rails'url_for
这样的东西,或者说router.get('parent_route')
(或controller.get('parent_route')
)的方式。
任何指针或想法?感谢。
答案 0 :(得分:12)
这是在2013年为ember v0.9.8或其他东西回答的,从那时起框架已经走了很长一段路。我认为当前版本的框架可能有更好的解决方案。既然,我与Ember没有联系,无法真正更新这个答案!
从源代码中的私有函数启发,将以下方法添加到返回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;
}
}
})
使用内部路线如下
App.SomeRoute = Ember.Route.extend({
events: {
goBack: function(){
this.transitionTo(this.getParentRoute());
}
}
})
车把
<script type="text/x-handlebars" data-template-name="some">
<a href="#" {{action goBack}}>Back</a>
</script>
对于实际代码,请打开this并为 function parentRoute
执行CTRL + F
答案 1 :(得分:6)
您可以在模板中使用通用{{action }}
,但在路由器中实现“返回”的细节。这是因为Ember bubbles up goBack
事件首先发送到控制器,然后是当前路由,然后是父路由等,直到找到动作处理程序。在这种情况下,控制器上没有匹配操作,因此它由当前路由处理。这使您的模板/视图/控制器与特定内容无关,但是当您连接小部件时,您可以指定应该如何处理“返回”。
在示例中,相同的按钮会使路线更改为不同的路线,具体取决于当前路线的路线:
/posts
中的/
/posts/new
中的/posts
使用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');
}
}
});
模板:
<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>
答案 2 :(得分:3)
基于Mudasi Ali的领导和审阅Ember v1.5来源,我使用以下内容:
Coffeescript(如果你想要JS / ES,请使用coffeescript.org进行转换):
Ember.Route.reopen
parentRoute: Em.computed ->
r = @router.router
if r.currentTransition
handlerInfos = r.currentTransition.state.handlerInfos
else
handlerInfos = r.state.handlerInfos
handlerInfos = this.router.router.state.handlerInfos
return unless handlerInfos
parent = @
for info in handlerInfos
break if info.handler == @
parent = info.handler
parent
parentRouteName: Em.computed.alias('parentRoute.routeName')
parentController: ->
@controllerFor @get('parentRouteName')
parentModel: ->
@modelFor @get('parentRouteName')
上面提供了所有路由上的属性parentRoute
和parentRouteName
以及两个分别返回父控制器和模型的便捷函数parentController()
和parentModel()
。适用于许多情况,特别是如果您将资源编辑为嵌套路径。
您还可以在视图/控制器等中定义一些操作,以进行取消/返回处理,如下所示:
Ember.Route.reopen
actions:
goBack: ->
@transitionTo @get('parentRouteName')
如果你有一个深层路由层次结构并想说跳过一个中间路由,你只需要覆盖goBack,如下所示:
App.SomeIntermediateRouteToSkipOnBack = Em.Route.extend
actions:
goBack: ->
# skip the immediate parent and use the grandparent route
@transitionTo @get('parentRoute.parentRouteName)
答案 3 :(得分:3)
更新了Ember 2.6
在档案app/initializers/parent_route.js
import Ember from 'ember';
var alreadyRun = false;
export default {
name: 'parent-route',
initialize: function() {
if (alreadyRun) {
return;
} else {
alreadyRun = true;
}
Ember.Route.reopen({
parentRoute: Ember.computed(function() {
let handlerInfos, i, info, len, parent, r;
r = this.router.router;
if (r.activeTransition) {
handlerInfos = r.activeTransition.state.handlerInfos;
} else {
handlerInfos = r.state.handlerInfos;
}
if (!handlerInfos) {
return;
}
parent = this;
for (i = 0, len = handlerInfos.length; i < len; i++) {
info = handlerInfos[i];
if (info.handler === this) {
break;
}
parent = info.handler;
}
return parent;
}),
parentRouteName: Ember.computed.alias('parentRoute.routeName'),
parentController: Ember.computed(function() {
return this.controllerFor(this.get('parentRouteName'));
}),
parentModel: Ember.computed(function() {
return this.modelFor(this.get('parentRouteName'));
})
});
}
};
在您的路线中,您可以访问像this.get('parentController')
这样的父控件,以及this.get('parentModel')