2012-07-13 14 views
8

Data una pagina che utilizza Backbone.js per avere una raccolta legata a una vista (RowsView, crea un <ul>) che crea viste secondarie (RowView, crea <li>) per ogni modello nella raccolta, ho un problema di impostazione editing in linea per quei modelli nella collezione.Trova una vista Backbone.js se conosci il modello?

ho creato un metodo edit() sul RowView opinione che sostituisce i li contenuti con una casella di testo, e se l'utente preme tab mentre in quella casella di testo, mi piacerebbe far scattare il metodo del prossimo View nel edit() elenco.

posso ottenere il modello del prossimo modello della collezione:

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

Ma la domanda è, come trovare la vista che è attaccato a quel modello. La vista genitore RowsView non conserva un riferimento a tutte le viste secondarie; è render() metodo è solo:

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

Ho bisogno di riscriverlo per mantenere un array separato di puntatori a tutte le RowView s che ha sotto di essa? O c'è un modo intelligente per trovare la Vista a cui è collegato un Modello conosciuto?

Ecco un jsFiddle di tutto il problema: http://jsfiddle.net/midnightlightning/G4NeJ/

risposta

11

Non è elegante per memorizzare un riferimento alla vista nel modello, tuttavia è possibile collegare una visualizzazione con una modella con eventi, fare questo:

// 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 ascoltare l'evento prepareEdit e in quella chiamata ascoltatore di modifica(), qualcosa di simile:

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

direi che il vostro RowsView dovrebbe tenere traccia del suo componente RowView s. I singoli RowView sono davvero parti di RowsView e ha senso che una vista tenga traccia delle sue parti.

Così, il vostro RowsView avrebbe un metodo render un po 'come questo:

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

Poi basta un modo per convertire un Tab ad un indice in this.child_views.


Un modo è quello di utilizzare gli eventi, viste Backbone hanno Backbone.Events misto in modo da vista può innescare eventi in se stessi e l'altro può ascoltare quegli eventi.Nella tua RowView si potrebbe avere questo:

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

e la tua RowsView sarebbe v.on('tab-next', this.edit_next); nel this.collection.map e si potrebbe avere un edit_next sorta di simile:

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/

Una variante questo sarebbe quello di aggiungere un riferimento allo RowsView allo RowView se poi tab_next potrebbe direttamente chiama this.parent_view.edit_next().


Un'altra opzione è quella di mettere il gestore keydown all'interno RowsView. Questo aggiunge un po 'di accoppiamento tra il RowView e RowsView, ma che probabilmente non è un grosso problema in questo caso, ma è un po' più brutto rispetto alla soluzione evento:

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/

Problemi correlati