2012-04-03 5 views
32

Vorrei archiviare diversi oggetti nello stesso array di contenuto del controller e renderizzare ciascuno utilizzando un modello di visualizzazione appropriato, ma idealmente la stessa vista.Selezionare il modello di visualizzazione per tipo di modello/valore oggetto utilizzando Ember.js

Sto emettendo gli oggetti lista usando il codice qui sotto. Sono attualmente identici, ma mi piacerebbe poterne usare di diversi.

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

Una versione ridotta della vista è riportata di seguito. Le altre funzioni che non ho incluso potrebbero essere utilizzate per uno qualsiasi degli oggetti, indipendentemente dal modello. Quindi avrei idealmente una vista (anche se ho letto alcuni articoli sui mixin che potrebbero aiutare se non).

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

miei primi test nel permettere che diversi tipi di oggetti sono finiti con un sacco di condizioni all'interno 'semplice-row-preview' - sembrava terribile!

Esiste un modo per controllare dinamicamente il templateName o la vista utilizzata durante l'iterazione sul mio array di contenuto?

UPDATE

Grazie molto per i due intervistati. Il codice finale in uso sulla vista è sotto. Alcuni dei miei modelli sono simili e mi piaceva l'idea di poter passare da un modello all'altro (o una sorta di "stato") alla mia applicazione.

<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> 

risposta

102

È possibile rendere templateName una proprietà e quindi elaborare quale modello utilizzare in base al contenuto.

Ad esempio, questo instanceof usa per impostare un modello in base al tipo di oggetto:

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

Ecco un violino con un esempio di lavoro di quanto sopra: http://jsfiddle.net/rlivsey/QWR6V/

+2

Questa è una risposta molto buona, ma purtroppo, questo è il caso in cui la vista non viene aggiunta tramite un helper del manubrio ma come una classe che viene prelevata automagicamente dalla brace. In tal caso, non puoi accedere a 'content' né a' controller' (qui di seguito: http://stackoverflow.com/questions/15337065/how-to-get-any-controller-instance-from-init- metodo-di-una-vista). La mia soluzione in questo caso era di avere un metodo osservando 'controller.content' e impostando la vista di conseguenza in questa funzione tramite' this.set ('currentView', vista) ' – vanthome

16

basato sulla soluzione di @ rlivsey, ho aggiunto la funzionalità per modificare il modello quando una proprietà cambia, vedere 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: Questo non funziona più. A volte la vista tenta di essere visualizzata quando viene distrutta, generando un errore. –