2012-04-03 5 views
32

Chciałbym przechowywać różne obiekty w tej samej macierzy zawartości kontrolera i renderować każdy z nich za pomocą odpowiedniego szablonu widoku, ale najlepiej tego samego widoku.Wybierz szablon widoku według typu modelu/wartości obiektu za pomocą Ember.js

Generuję obiekty listy używając poniższego kodu. Są obecnie identyczne, ale chciałbym móc używać różnych.

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

Skrócona wersja widoku znajduje się poniżej. Inne funkcje, których nie uwzględniłem, mogą być użyte do dowolnego obiektu, niezależnie od modelu. Więc najlepiej byłoby mieć jeden widok (chociaż przeczytałem kilka artykułów na temat mixins, które mogłyby pomóc, jeśli nie).

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

Moje pierwsze kilka testów na dopuszczenie różnych typów obiektów zakończyło się mnóstwem warunków w ramach "prostego podglądu wiersza" - wyglądało to okropnie!

Czy istnieje sposób dynamicznego kontrolowania nazwy szablonu lub widoku używanego podczas iterowania nad moją macierzą zawartości?

UPDATE

Dzięki bardzo do dwóch respondentów. Ostateczny kod używany w widoku znajduje się poniżej. Niektóre z moich modeli są podobne i podobało mi się, że mogę przełączać się między szablonami (lub pewnego rodzaju "stanem") w mojej aplikacji.

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

Odpowiedz

102

Można ustawić właściwość templateName jako własność, a następnie ustalić, jaki szablon ma być używany na podstawie zawartości.

Na przykład ten używa instanceof do ustawienia szablonu na podstawie typu obiektu:

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

Oto skrzypce z przykładu wykonania powyższego: http://jsfiddle.net/rlivsey/QWR6V/

+2

jest to bardzo dobra odpowiedź, ale niestety, to przypadek, w którym widok nie jest dodawany za pomocą pomocnika kierownicy, ale jako klasa, która jest pobierana automagicznie przez ember. W takim przypadku nie masz dostępu do "treści" ani "kontrolera" (omawiane tutaj: http://stackoverflow.com/questions/15337065/how-to-get-any-controller-instance-from-init- metoda widzenia). Moim rozwiązaniem w tym przypadku było posiadanie metody obserwującej 'controller.content' i ustawienie widoku odpowiednio w tej funkcji poprzez' this.set ('currentView', view) ' – vanthome

16

oparciu o rozwiązania @ rlivsey dodałem funkcjonalność, aby zmienić szablon, gdy zmiany własności, patrz 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

Uwaga: To już nie działa. Widok będzie się czasami wyświetlał, gdy zostanie zniszczony, powodując błąd. –

Powiązane problemy