2012-04-03 9 views
32

Me gustaría almacenar diferentes objetos en la misma matriz de contenido de controlador y renderizar cada uno utilizando una plantilla de vista apropiada, pero idealmente la misma vista.Seleccionar vista de plantilla por tipo de modelo/valor de objeto usando Ember.js

Estoy saliendo objetos de la lista usando el siguiente código. Actualmente son idénticos, pero me gustaría poder usar otros diferentes.

<script type="text/x-handlebars"> 
    {{#each App.simpleRowController}} 
    {{view App.SimpleRowView class="simple-row" contentBinding="this"}} 
    {{/each}} 
</script> 

Abajo figura una versión reducida de la vista. Las otras funciones que no he incluido podrían usarse con cualquiera de los objetos, independientemente del modelo. Entonces, idealmente, tendría una vista (aunque he leído algunos artículos sobre mixinas que podrían ayudar si no fuera así).

<script> 
    App.SimpleRowView = Em.View.extend({ 
    templateName: 'simple-row-preview', 
    }); 
</script> 

Mis primeras pruebas en diferentes tipos de objetos que permiten terminó con un montón de condiciones dentro de 'simple fila-preview' - es un aspecto horrible!

¿Hay alguna manera de controlar dinámicamente el templateName o la vista utilizada al iterar sobre mi matriz de contenido?

ACTUALIZACIÓN

Muchas gracias a los dos demandados. El código final en uso en la vista está debajo. Algunos de mis modelos son similares, y me gustó la idea de poder cambiar de plantilla (o una especie de 'estado') en mi aplicación.

<script> 
    App.SimpleRowView = Em.View.extend({ 
    templateName: function() { 
     return Em.getPath(this, 'content.template'); 
    }.property('content.template').cacheable(), 
    _templateChanged: function() { 
     this.rerender(); 
    }.observes('templateName'), 
    // etc. 
    }); 
</script> 

Respuesta

102

Puede hacer que templateName sea una propiedad y luego determinar qué plantilla usar en función del contenido.

Por ejemplo, este utiliza instanceof para establecer una plantilla basada en el tipo de objeto:

App.ItemView = Ember.View.extend({ 
    templateName: function() { 
     if (this.get("content") instanceof App.Foo) { 
      return "foo-item"; 
     } else { 
      return "bar-item"; 
     } 
    }.property().cacheable() 
}); 

Así es un violín con un ejemplo de trabajo de las anteriores: http://jsfiddle.net/rlivsey/QWR6V/

+2

Esta es una muy buena respuesta, pero, por desgracia, este es el caso donde la vista no se agrega a través de un auxiliar de manubrio sino como una clase que se recoge automágicamente por ascua. En ese caso, no podrá acceder a 'content' ni a' controller' (se trata aquí: http://stackoverflow.com/questions/15337065/how-to-get-any-controller-instance-from-init- método-de-una-vista). Mi solución en este caso era tener un método que observara el 'controller.content' y establecer la vista correspondiente en esta función a través de' this.set ('currentView', view) ' – vanthome

16

Basado en la solución de @ rlivsey, he añadido la funcionalidad de cambiar la plantilla cuando una propiedad cambia, ver http://jsfiddle.net/pangratz666/ux7Qa/

App.ItemView = Ember.View.extend({ 
    templateName: function() { 
     var name = Ember.getPath(this, 'content.name'); 
     return (name.indexOf('foo') !== -1) ? 'foo-item' : 'bar-item'; 
    }.property('content.name').cacheable(), 

    _templateChanged: function() { 
     this.rerender(); 
    }.observes('templateName') 
}); 
+0

Nota: Esto ya no funciona. La vista a veces intenta renderizarse cuando se destruye, arrojando un error. –

Cuestiones relacionadas