2012-07-13 8 views
8

Angesichts einer Seite, die Backbone.js verwendet, um eine Collection an eine Ansicht gebunden zu haben (RowsView, erstellt eine <ul>), die Unteransichten erstellt (RowView, erstellt <li>) für jedes Modell in der Sammlung, habe ich ein Problem einrichten Inline-Bearbeitung für diese Modelle in der Sammlung.Suchen Sie eine Backbone.js Ansicht, wenn Sie das Modell kennen?

Ich habe eine edit() Methode auf der RowView Ansicht, dass den li Inhalt mit einem Textfeld, und wenn der Benutzer drückt tab während in diesem Textfeld, ich mag löse die edit() Methode der nächsten Ansicht in dem ersetzt Liste.

kann ich das Modell des nächsten Modells in der Sammlung erhalten:

// within a RowView 'keydown' event handler 
var myIndex = this.model.collection.indexOf(this.model); 
var nextModel = this.model.collection.at(myIndex+1); 

Aber die Frage ist, wie die Ansicht zu finden, die zu diesem Modell angeschlossen ist. Die übergeordnete Ansicht RowsView View enthält keinen Verweis auf alle untergeordneten Ansichten. es render() Methode ist einfach:

this.$el.html(''); // Clear 
this.model.each(function (model) { 
    this.$el.append(new RowView({ model:model}).render().el); 
}, this); 

Benötige ich es neu zu schreiben, ein separates Array von Zeigern auf alle RowView s es unter ihm hat zu halten? Oder gibt es eine clevere Möglichkeit, die View zu finden, an die ein bekanntes Modell angehängt ist?

hier ein jsFiddle des ganzen Problems: http://jsfiddle.net/midnightlightning/G4NeJ/

Antwort

11

Es ist nicht elegant einen Verweis auf die Ansicht in Ihrem Modell zu speichern, aber Sie eine Ansicht mit einem Modell mit Ereignissen in Verbindung bringen könnten, dies zu tun:

// within a RowView 'keydown' event handler 
var myIndex = this.model.collection.indexOf(this.model); 
var nextModel = this.model.collection.at(myIndex+1); 
nextModel.trigger('prepareEdit'); 

in RowView auf das Ereignis hören prepareEdit und in diesem Hörer Anruf bearbeiten(), etwa so:

this.model.on('prepareEdit', this.edit); 
2

ich würde sagen, dass Ihre RowsView sollte die Komponente RowView s verfolgen. Die einzelnen RowView sind wirklich Teile der RowsView und es macht Sinn, dass eine Ansicht ihre Teile verfolgen sollte.

Also, Ihr RowsView würde eine render Methode Art wie folgt aus:

render: function() { 
    this.child_views = this.collection.map(function(m) { 
     var v = new RowView({ model: m }); 
     this.$el.append(v.render().el); 
     return v; 
    }, this); 
    return this; 
} 

Dann brauchen Sie nur einen Weg, um eine Tab auf einen Index in this.child_views zu konvertieren.


Ein Weg ist, Ereignisse, Backbone Ansichten Backbone.Events in gemischten haben zu verwenden, um Ansichten Ereignisse auf sich selbst und andere Dinge auslösen können auf diese Ereignisse hören.In Ihrem RowView Sie könnte dies:

events: { 
    'keydown input': 'tab_next' 
}, 
tab_next: function(e) { 
    if(e.keyCode != 9) 
     return true; 
    this.trigger('tab-next', this); 
    return false; 
} 

und Ihre RowsView würde v.on('tab-next', this.edit_next); im this.collection.map und man konnte eine edit_next Art wie dieses:

edit_next: function(v) { 
    var i = this.collection.indexOf(v.model) + 1; 
    if(i >= this.collection.length) 
     i = 0; 
    this.child_views[i].enter_edit_mode(); // This method enables the <input> 
} 

Demo: http://jsfiddle.net/ambiguous/WeCRW/

eine Variante Dies wäre, um einen Verweis auf die RowsView an die RowView s und dann tab_next könnte direkt hinzufügen Anruf this.parent_view.edit_next().


Eine weitere Option ist die keydown Handler innerhalb RowsView zu setzen. Dies fügt ein wenig Kopplung zwischen den RowView und RowsView aber das ist wahrscheinlich kein großes Problem in diesem Fall, aber es ist ein bisschen hässlicher als die Veranstaltung Lösung:

var RowsView = Backbone.View.extend({ 
    //... 
    events: { 
     'keydown input': 'tab_next' 
    }, 
    render: function() { 
     this.child_views = this.collection.map(function(m, i) { 
      var v = new RowView({ model: m }); 
      this.$el.append(v.render().el); 
      v.$el.data('model-index', i); // You could look at the siblings instead... 
      return v; 
     }, this); 
     return this; 
    }, 
    tab_next: function(e) { 
     if(e.keyCode != 9) 
      return true; 
     var i = $(e.target).closest('li').data('model-index') + 1; 
     if(i >= this.collection.length) 
      i = 0; 
     this.child_views[i].enter_edit_mode(); 
     return false; 
    } 
}); 

Demo: http://jsfiddle.net/ambiguous/ZnxZv/

Verwandte Themen