ember.js - Emberjs idiomáticos para rutas anidadas pero plantillas no anidadas
ember-router (1)
Podría definir la plantilla principal para mostrar solo la salida y tener una ruta de índice que se mostrará dentro de esa. Entonces para el recurso anidado puedes hacer lo mismo.
<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>
De esa manera no será un maestro / detalle.
El enrutador sería:
App.Router.map(function() {
this.resource(''user'', function() {
this.resource(''posts'', function() { });
});
});
Luego, si necesita obtener información sobre el padre, puede usar modelFor
. Entonces, si estuvieras en publicaciones, podrías hacer this.modelFor(''user'')
;
Aquí hay un jsbin que demuestra esto.
Espero que esto sea de ayuda.
Este es un seguimiento de Entendiendo las rutas de Ember .
Las vistas maestras / detalladas son excelentes, pero estoy tratando de tener una ruta URL jerárquica sin anidar sus plantillas. Sin embargo, todavía necesito acceso al modelo principal para cosas como los enlaces de la miga de pan y otras referencias.
Así que /users/1/posts
debería mostrar una lista de publicaciones para el usuario 1. Y /users/1/posts/1
debería mostrar la publicación 1 para el usuario 1, pero no debe mostrarse dentro de la {{outlet}}
la plantilla del user
. En su lugar, debe reemplazar completamente la plantilla de user
. Sin embargo, todavía necesito acceso al usuario actual en la plantilla de post
para poder enlazar con el usuario, mostrar el nombre del usuario, etc.
Primero probé algo como esto (Método # 1):
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''
});
}
});
Esto reemplazó la plantilla de user
con la post
uno, como se esperaba. Pero cuando hago clic en el botón Atrás del navegador, la plantilla de user
no vuelve a aparecer. Aparentemente, la vista de publicación se destruye, pero la vista principal no se vuelve a insertar. Hay algunas preguntas aquí que mencionan esto.
Luego lo puse a trabajar con algo como esto (Método # 2):
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''
});
Pero esto me parece un poco hacky y no muy SECO.
Primero, necesito recuperar al User
nuevamente en el PostRoute
y agregarlo como una variable ad-hoc al PostController
(esto no sería necesario si las rutas estuvieran correctamente anidadas y podría simplemente establecer una propiedad de needs: ''user''
en el PostController
). Además, esto puede o no tener un impacto en el back-end dependiendo de la implementación del adaptador de datos de brasas o cualquier tecnología que se use para recuperar los datos del servidor (es decir, puede causar una segunda llamada innecesaria para cargar el User
) .
También necesito una declaración adicional ''PostIndexController'' solo para agregar esa nueva dependencia, que no es un gran problema.
Otra cosa que no se siente bien es que /users/:user_id/posts
aparece dos veces en la configuración del enrutador (uno anidado y otro no).
Puedo lidiar con estos problemas y funciona, pero supongo que, en general, parece forzado y no tan elegante. Me pregunto si me estoy perdiendo alguna configuración obvia que me permita hacer esto con rutas anidadas regulares o si alguien tiene una recomendación para una forma más "Ember.js" de hacer esto.
Debería mencionar que, independientemente de los méritos técnicos del Método # 2, me tomó bastante tiempo descubrir cómo hacerlo funcionar. Tomó mucha búsqueda, lectura, experimentación, depuración, etc. para encontrar la combinación correcta de definiciones de ruta. Me imagino que este no es un caso de uso único y debería ser muy sencillo para un usuario configurar algo como esto sin pasar horas de prueba y error. Estaré encantado de escribir algunos consejos para esto en la documentación de Ember.js si termina siendo el enfoque correcto.
Actualizar:
Gracias a @spullen por aclarar esto. Mi caso no fue tan sencillo como el ejemplo porque algunas subrutas necesitan plantillas anidadas y otras no, pero la respuesta me ayudó a resolverlo. Mi implementación final se ve algo como esto:
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'' });
});
});
});
});
Así que ahora las posts
muestran en la plantilla de users
pero la post
reemplaza todo. comments
luego se procesan bajo la post
y los comment
, a su vez, los rendimientos bajo los comments
.
Todos ellos son sub-rutas de users
por lo que el modelo de usuario es accesible para todos ellos sin acrobacias, haciendo this.modelFor(''users'')
en cada Ruta donde sea necesario.
Así que las plantillas se ven así:
users
|- posts
post
|- comments
|-comment
No sé por qué se necesita la { path: '''' }
para la definición del recurso users.index
, pero si la saco, Ember no encuentra la ruta de los users
. Me encantaría deshacerme de ese último vestigio.