这是Understanding Ember routes的后续行动。
主视图/详细信息视图很棒,但我正在尝试使用分层URL路由而不嵌套模板。但是,我仍然需要访问父模型,例如面包屑链接和其他引用。
因此/users/1/posts
应显示用户1的帖子列表。/users/1/posts/1
应显示用户1的帖子1,但不应在user
模板的{{1}内呈现}}。相反,它应该完全取代{{outlet}}
模板。但是,我仍然需要访问user
模板中的当前用户,以便我可以链接回用户,显示用户的姓名等。
首先我试过这样的事情(方法#1):
post
这会将App.Router.map(function() {
this.resource('user', { path: '/users/:user_id' }, function() {
this.resource('posts', function() {
this.resource('post', { path: '/:post_id' });
});
});
});
...
App.PostRoute = Ember.Route.extend({
model: function(params) {
return App.Post.find(params.post_id);
},
renderTemplate: function() {
this.render('post', {
into: 'application'
});
}
});
模板替换为user
模板,如预期的那样。但是,当我单击浏览器的后退按钮时,post
模板不会再次渲染。显然,后视图被销毁但父视图未被重新插入。这里有几个问题提到了这一点。
然后我让它用这样的东西(方法#2):
user
但这对我来说似乎有些苛刻而且不是很干。
首先,我需要在App.Router.map(function() {
this.resource('user', { path: '/users/:user_id' }, function() {
this.resource('posts');
this.resource('post', { path: '/users/:user_id/posts' }, function() {
this.resource('post.index', { path: '/:post_id' });
});
});
...
App.PostRoute = Ember.Route.extend({
model: function(params) {
return App.User.find(params.user_id);
},
setupController: function(controller, model) {
controller.set('user', model);
}
});
App.VideoIndexRoute = Ember.Route.extend({
model: function(params) {
return App.Post.find(params.post_id);
}
});
App.PostIndexController = Ember.ObjectController.extend({
needs: 'post'
});
中再次检索User
并将其作为临时变量添加到PostRoute
(如果路线是正确嵌套,我可以在PostController
中设置needs: 'user'
属性。此外,这可能会或可能不会对后端产生影响,具体取决于ember-data的适配器实现或用于从服务器检索数据的任何技术(即它可能导致不必要的第二次调用加载{{ 1}})。
我还需要一个额外的`PostIndexController'声明来添加新的依赖项,这不是什么大问题。
另一件感觉不对的是PostController
在路由器配置中出现两次(一个嵌套,一个不嵌套)。
我可以处理这些问题而且它确实有效,但我想,总的来说,这似乎是强迫而不是优雅。我想知道我是否缺少一些明显的配置,这些配置可以让我使用常规的嵌套路由来执行此操作,或者如果有人建议使用更多“Ember.js方式”来执行此操作。
我应该提一下,不管方法#2的技术优点如何,我花了很长时间才弄清楚如何使它工作。它需要大量的搜索,阅读,试验,调试等才能找到合适的路径定义组合。我认为这不是一个非常独特的用例,用户可以非常直接地设置这样的东西,而无需花费数小时的试验和错误。如果最终成为正确的方法,我会很高兴在Ember.js文档中写下一些提示。
感谢@spullen澄清这一点。我的情况并不像示例那么简单,因为有些子路径需要嵌套模板而有些不需要,但答案帮助我解决了问题。我的最终实现看起来像这样:
User
现在/users/:user_id/posts
呈现App.Router.map(function() {
this.resource('users', { path: '/users/:user_id' }, function() {
this.resource('users.index', { path: '' }, function() {
this.resource('posts')
});
this.resource('post', { path: '/posts/:post_id' }, function() {
this.resource('comments', function() {
this.resource('comment', { path: '/:comment_id' });
});
});
});
});
模板,但posts
取代了所有内容。 users
然后在post
和comments
下呈现,然后在post
下呈现。
所有这些都是comment
的子路径,因此所有人都可以访问用户模型而无需杂技,只需在每个需要的路线中执行comments
。
所以模板看起来像这样:
users
我不知道为什么this.modelFor('users')
资源定义需要users
|- posts
post
|- comments
|-comment
,但如果我把它拿出来,Ember找不到{ path: '' }
路由。我很想摆脱最后的遗迹。
答案 0 :(得分:9)
您可以将父模板定义为仅显示插座并具有将在其中显示的索引路径。然后,对于嵌套资源,您可以执行相同的操作。
<script type="text/x-handlebars" data-template-name="user">
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="user/index">
<h2>user/index</h2>
</script>
<script type="text/x-handlebars" data-template-name="posts">
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="posts/index">
<h2>posts/index</h2>
</script>
这样它就不会成为主人/细节。
路由器将是:
App.Router.map(function() {
this.resource('user', function() {
this.resource('posts', function() { });
});
});
然后,如果您需要获取有关父级的信息,可以使用modelFor
。因此,如果你在帖子中,你可以this.modelFor('user')
;
这是展示这一点的jsbin。
希望这有用。