2012-09-26 79 views
10

Estoy escribiendo una aplicación con EmberJS v1.0.pre. Tengo un ArrayController que contiene una lista de todas las personas. Hay un montón de vistas anidadas que muestran a la persona, sus mascotas y las notas de cada mascota.EmberJS anidadas vistas y controladores

|----------------------------------------| 
| John         | <- Person 
|----------------------------------------| 
| Quincy (Dog)       | <- Pet 
|  - Super ornery      | <- Note 
|  - Likes XYZ Dog food    | 
|  - Will eat your socks    | 
|          | 
| Tom (Cat)       | 
| - Always (not) catching mice  | 
|          | 
|----------------------------------------| 
| Roger         | 
|----------------------------------------| 
| V (Dog)        | 
| - Likes XYZ Dog food    | 
| - Sneezes, but it's ok    | 
|          | 
|----------------------------------------| 
| ...         | 

Desde el punto de vista MVC pura se siente como debería haber un controlador para cada niño, pero no puedo encontrar la manera de lograr que en Ember. Está el controlador Array superior y luego todas las vistas individuales. Si quiero eliminar una nota o editarla, parece que necesito pasar el contexto de la vista al controlador.

// in the view 
click: function() { 
    this.get('controller').updateNote(this.get('content')) 
} 

Esto se siente realmente mal para mí, se supone que la Vista no es la fuente autorizada de los datos. Mi hipótesis es que un ArrayController sería una instancia de un itemControlerClass junto con el itemViewClass.

ACTUALIZACIÓN: He creado una fiddle Para ilustrar mejor mi problema. La funcionalidad es intencionalmente incompleta, el propósito es finalizar la funcionalidad aumentando el contenido cuando se hace clic en un elemento de la lista.

ACTUALIZACIÓN: Lo siento, he eliminado el violín por accidente! Estoy trabajando en una solución final, así que intentaré crear un nuevo violín con la solución.

+0

Vaya a través de este http://emberjs.com/guides/outlets/ –

+0

No hay información firme en esa guía sobre mi problema. Lo he leído antes, y seguiré haciéndolo, pero aún no he encontrado nada. – noazark

+0

Mira esto y luego http://stackoverflow.com/questions/12595496/how-can-i-build-a-recursive-view-in-ember/12602743#comment17008361_12602743 –

Respuesta

12

"Desde el punto de vista MVC pura se siente como debería haber un controlador para cada niño"

No es necesario un controlador para cada elemento, pero en lugar de una ArrayController para cada colección de objetos (Gente, Mascotas, Notas). Por cierto, cualquier acción sobre objetos secundarios (perros, notas) no deben ser pasados ​​a App.PersonsController. Eso rompería el principio Separation of Concerns.

Ember.Router docs cubre el caso en el que desea anidar vistas en un solo objeto (por ejemplo, /:people_id). Pero desea anidar vistas para una matriz de objetos. No puedo pensar en una forma de anidar {{outlet}} vistas, pero puede hacer lo siguiente:

Cargue los objetos Personas, Mascotas, Notas en 3 ArrayControllers, y delegue acciones en objetos secundarios a su ArrayController correspondiente.

App.Router = Ember.Router.extend({ 
    root: Ember.Route.extend({ 
    route: '/', 
    persons: Ember.Route.extend({ 
     connectOutlets: function(router) { 

      router.get('applicationController').connectOutlet('persons'); 
      // App.Note.find() fetches all Notes, 
      // If you are not using ember-data, make sure the notes are loaded into notesController 
      router.set('notesController.content', App.Note.find()); 
      router.set('petsController.content', App.Pet.find()); 
     } 
    }) 
    }) 
}); 

Y entonces su plantilla people debe verse como:

{{#each person in people}} 
    <h1>My name is {{person.name}}</h1> 

    {{#each pet in person.pets}} 
    I have a pet with name {{pet.name}} 
    <a {{action delete pet target="App.router.petsController">Delete pet</a> 
    {{/each}}  

    {{view Ember.TextField valueBinding="myNewPetName" type="text"}} 
    <a {{action create myNewPetName person target="controller"}}> 
    Add a new pet for this person 
    </a> 


    {{#each note in person.notes}} 
    <!-- delete, create, edit ... --> 
    {{/each}} 

Como se puede ver, las acciones sobre los objetos secundarios se delegan a su controlador (PET -> petsController), pasando el objeto como el contexto. En el caso de la acción create, el controlador necesita saber a qué persona la mascota belongsTo. Por lo tanto, pasamos por 2 contextos: la persona y las propiedades de la mascota (por simplicidad, solo asumí un nombre para la mascota).

En sus App.petsControllers usted debe tener acciones a lo largo de las líneas:

App.PetsController = Ember.ArrayController.extend({ 
    delete: function(e) { 
    var context = e.context; 
    this.get('content').removeObject(context); 
    // Also, if you use ember-data, 
    // App.Pet.deleteRecord(context); 
    }, 

    create: function(e) { 
    var petName = e.contexts[0] 
    var person = e.contexts[1]; 
    this.get('content').pushObject({name: petName, person: person}); 
    // with ember-data: 
    // App.Pet.createRecord({name: petName, person: person}); 
    } 
}); 
+1

Este es fácilmente el ejemplo más completo que he visto de mi problema, ¡gracias! Tomaré esta respuesta y correré con ella. Sin embargo, hay algunos problemas que todavía debo abordar. Aprobar el contexto de la vista es mi queja original sobre este problema, pero parece inevitable. Además, los controladores no pueden simplemente configurarse para todas las Notas, ya que son hijos de Mascotas (literalmente integradas), y lo mismo ocurre con Mascotas y Personas. Para mí, esto no parece un problema arquitectónico. Tendré que establecer el contexto principal primero, supongo. Actualizaré mi pregunta con cualquier cosa que descubra. Gracias de nuevo. – noazark

1

Debería utilizar puntos de venta. son poco '' marcadores de posición en vistas Ember que se pueden manejar con diferentes controladores.

Hay una explicación razonable de ellas en el enlace de arriba, donde ya se ha comprobado y no encontró nada. Pero antes de volver a eso, lea esto primero: http://trek.github.com/

Si alguno de estos aún no lo ayuda, hágale saber y armaré un axample para usted.

+0

He leído ambos artículos, incluso antes de mi publicación. También estoy utilizando puntos de venta, sin embargo, los puntos de venta no delegan la responsabilidad del contenido en un controlador separado. Gracias por su oferta para armar un ejemplo, me encantaría ver uno. También encenderé algo en jsfiddle para explicar mejor mi problema. – noazark

+0

He actualizado mi pregunta con un [violín] (http://jsfiddle.net/noazark/HmHK3/). Gracias por tu ayuda continua. – noazark

1

Creo que this es lo que estás buscando, mira, es bastante sencillo, también puedes consultar el ejemplo this. Básicamente puede lograr lo que quiere con tomas de corriente, enrutadores y acciones para conectar todos sus puntos de venta.

+0

Voy a tomar otra puñalada. Este artículo, https://gist.github.com/3002177, también ha sido de gran ayuda. Creo que mi problema ha sido utilizar ArrayController. ¿Cuándo realmente debería ser solo un controlador con enchufes? ¿Tiene sentido? – noazark

+0

¿Alguna posibilidad de que pueda proporcionar un ejemplo diferente, más pertinente? El que proporcionó no tiene ningún paralelo con mi pregunta. Específicamente, mi problema no es con el enrutamiento, sino con la delegación de control a los recursos anidados. Los outlets son interesantes, pero incluso con todas las sugerencias para usarlos, todavía no hay un ejemplo útil de cómo resuelven mi problema. – noazark

0

Soy nuevo en Ember y he estado buscando una manera de hacer algo similar. En el ArrayController de nivel superior, que acabo de utilizar la propiedad itemController y funcionó muy bien:

App.PeopleController = Ember.ArrayController.extend({ 
    itemController: "Person" 
}); 

App.PersonController = Ember.ObjectController.extend //... 

Mi solución completa está en this js fiddle. Lamentablemente, la forma en que estoy obteniendo las instancias de PetController funciona bien.

+0

Las actualizaciones desde v1.0pre han sido muy útiles y he tenido mucha mejor suerte. ¡Profundizaré en lo que hiciste y veré cómo va! – noazark

Cuestiones relacionadas