2012-04-26 11 views
10

Ich habe eine Sammlung von Modellen, die ich in einer Tabellenansicht rendern möchte. Jedes Modell sollte durch eine einzelne Zeile in der Tabelle dargestellt werden, und diese Zeile sollte mithilfe einer Vorlage generiert werden. Ich sollte in der Lage sein, Event-Handler an diese Zeile anzuhängen (sagen wir Klick), die nach dem Ereignis einige spezifische Informationen bezüglich des Modells, das dieser Zeile zugeordnet ist, ausgeben.Backbone-Tabellenansicht Row-View konsumieren - wie strukturiert man?

Eine übliche Art, wie ich ähnliche Dinge gesehen habe, ist, jede Zeile in ihre eigene Ansicht zu zerlegen, und eine Elternansicht (sagen wir die Tabelle in diesem Fall) die Zeilenansicht zu verwenden, um die HTML zu generieren in deinen Code aufnehmen Ich kann jedoch nicht herausfinden, wie das mit Vorlagen funktioniert.

In diesem Fall kann ich keine Ereignisse speziell an die RowView anhängen, da es keinen Verweis auf ein dom-Element (für Backbone) hat, es gibt einfach eine Zeichenfolge zurück. Wie kann ich erreichen, was ich will, während ich eine Vorlage für maximale Kapazität verwende?

Die Frage bezieht sich nicht speziell auf Ereignisse, Templating oder die Verwendung verschachtelter Ansichten, sondern eher auf den richtigen Weg, um Backbone zu verwenden, um diese Art von Ausgabe zu erreichen.

Beispielcode (auch in einem fiddle):

/** View representing a table */ 
var TableView = Backbone.View.extend({ 
    tagName: 'table', 
    render: function() { 
     var rows = _.map(this.collection.models, function(p) { 
      return new RowView({model: p}).render();       
     }); 
     $('body').html(this.$el.html(rows.join(''))); 
    } 
}); 

/** View representing a row of that table */ 
var RowView = Backbone.View.extend({ 
    render: function() { 
     // imagine this is going through a template, but for now 
     // lets just return straight html. 
     return '<tr>' + 
       '<td>' + this.model.get('name') + '</td>' + 
       '<td>' + this.model.get('age') + '</td>' + 
       '</tr>'; 
    } 
}); 

var data = [ 
    {'name': 'Oli', 'age': 25}, 
    {'name': 'Sarah', 'age': 20}]; 

/** Collection of models to draw */ 
var peopleCollection = new Backbone.Collection(data); 
var tableView = new TableView({collection: peopleCollection}); 
tableView.render(); 

Thank you!

Antwort

11

Eine Möglichkeit, mit einer Hierarchie von Ansichten umzugehen, besteht darin, dass jede Ansicht ihre untergeordneten Elemente rendert und an ihre el anfügt. Die Ereignisse werden dann von jeder Ansicht entsprechend ihrem Modell/ihrer Sammlung behandelt.

Um Ihre HTML als Ansicht el zu injizieren und damit das Containerelement steuern, können Sie die setElement Methode

setElementview.setElement(element)

verwenden Wenn Sie ein Backbone Ansicht anwenden möchten Verwenden Sie setElement für ein anderes DOM-Element, das auch die zwischengespeicherte $ el-Referenz erstellt und die delegierten Ereignisse der Ansicht vom alten Element in das neue Element verschiebt.

Ihr Beispiel könnte als

var rowTemplate=_.template("<tr>"+ 
    "<td class='name'><%= name %></td>"+ 
    "<td class='age'><%= age %></td>"+ 
    "</tr>"); 

/** View representing a table */ 
var TableView = Backbone.View.extend({ 
    tagName: 'table', 

    initialize : function() { 
     _.bindAll(this,'render','renderOne'); 
    }, 
    render: function() { 
     this.collection.each(this.renderOne); 
     return this; 
    }, 
    renderOne : function(model) { 
     var row=new RowView({model:model}); 
     this.$el.append(row.render().$el); 
     return this; 
    } 
}); 

/** View representing a row of that table */ 
var RowView = Backbone.View.extend({ 
    events: { 
     "click .age": function() {console.log(this.model.get("name"));} 
    }, 

    render: function() { 
     var html=rowTemplate(this.model.toJSON()); 
     this.setElement($(html)); 
     return this; 
    } 
}); 

var data = [ 
    {'name': 'Oli', 'age': 25}, 
    {'name': 'Sarah', 'age': 20}]; 

/** Collection of models to draw */ 
var peopleCollection = new Backbone.Collection(data); 
var tableView = new TableView({collection: peopleCollection}); 
$("body").append(tableView.render().$el); 

Und ein Fiddle http://jsfiddle.net/9avm6/5/

+0

'setElement' das Stück war neu geschrieben werden, ich vermisst gewesen war - danke! –

+0

genial. Eine Frage, können Sie den Aufruf _.bindAll näher ausführen? Ich verstehe, dass es "das" zum Zeitpunkt des Aufrufs der Funktionen nützlicher machen soll, aber was bedeutet der Aufruf in dieser Form? An welche Ereignisse binden Sie render und renderOne? Warum binden Sie renderOne an irgendetwas? Vielen Dank! – Nicolas78

+0

@ Nicolas78 _.bindAll garantiert, dass "this" in render und renderOne zum Beispiel die Ansicht ist und nicht das Element, das das Ereignis ausgelöst hat. Nicht sehr nützlich hier, keine Bindung eingestellt, aber Render konnte auf einem collection.reset und renderOne auf einer Sammlung aufgerufen werden.add – nikoshr

Verwandte Themen