2012-04-16 15 views
5

Sto usando backbone.js per implementare un buddy list aka Roster. La mia opinione spina dorsale per la raccolta Roster e individuale rosterEntry sono i seguenti:Backbone.js: rimuovi un elemento da una collezione

Slx.Roster.Views.RosterEntry = Backbone.View.extend({ 
    tagName: "li", 
    className : "rosterEntry clearfix", 
    templateSelector: '#rosterEntryTemplate', 

    initialize: function() { 
     _.bindAll(this, 'render'); 
     this.model.bind('change', this.render); 
     this.model.bind('remove', this.remove); 
     this.template = _.template($("#rosterEntryTemplate").html()); 
    }, 

    remove: function() { 
     debug.log("Called remove event on model"); 
     $(this.el).remove(); 
    }, 
    render: function() { 
     var renderedContent = this.template(this.model.toJSON()); 
     this.id = this.model.Id; 
     $(this.el).attr('id', "friendid-" + this.model.get("id")).html(renderedContent); 
     return this; 
    } 
}); 

    Slx.Roster.Views.Roster = Backbone.View.extend({ 
     el: "div#roster-container", 
     initialize: function() { 
      _.bindAll(this, 'render', 'add', 'remove'); 
      this.template = _.template($("#rosterTemplate").html()); 
      this.collection.bind('reset', this.render); 
      this.collection.bind('add', this.add); 
      this.collection.bind('remove', this.remove); 
     }, 
     add: function (rosterEntry) { 
      var view = new Slx.Roster.Views.RosterEntry(
       { 
        model: rosterEntry 
       }); 
      $(this.el).append(view.render().el); 
     }, 
     remove: function (model) { // if I ommit this then the whole collection is removed!! 
      debug.log("called remomve on collection"); 
     }, 
     render: function() { 
      var $rosterEntries, collection = this.collection; 

      $(this.el).html(this.template({})); 
      $rosterEntries = this.$('#friend-list'); 

      _.each(collection.models, function (model) { 
       var rosterEntryView = new Slx.Roster.Views.RosterEntry({ 
        model: model, 
        collection: collection 
       }); 

       $(this.el).find("ul#friend-list").append(rosterEntryView.render().el); 
      }, this); 

      return this; 
     } 
    }) 

sto testando per ora utilizzando la console di Firebug e possono popolare il roster bene eseguendo il seguente:

collection = new Slx.Roster.Collection 
view = new Slx.Roster.Views.Roster({collection:collection}) 
collection.fetch() 

l'aggiunta a una raccolta funziona anche bene, eseguendo il seguente nella console di Firebug:

collection.add(new Slx.Roster.Model({username:"mickeymouse"})

e il nuovo rosterEntry sono stati aggiunti al menu di selezione.

Il mio problema è che collection.remove(5) rimuove dalla raccolta in memoria, ma non fa nulla per aggiornare il DOM.

Stranamente, se si omette la funzione remove() dalla Visualizzazione roster, tutte le voci nel roster vengono rimosse. Se aggiungo questo metodo con nient'altro che un log di console, viene chiamato il metodo di rimozione su entrambe le viste Roster e RosterEntry, anche se non sono sicuro del perché, ma sono fuori servizio!

["Called remove event on model"] 
["called remomve on collection"] 

se si elimina la funzione di rimozione dal modello RosterEntry ottengo questo errore:

TypeError: this.$el is undefined 
this.$el.remove(); 

Che cosa sto facendo di sbagliato? Come rimuovo l'elemento dal DOM quando viene rimosso dalla raccolta?

risposta

2

io pensi di avere un problema con il context in ogni definizione evento bind.

provare a cambiare questo:

this.model.bind('remove', this.remove); 

Per questo:

this.model.bind('remove', this.remove, this); 

So che avete cercato di risolvere questo con il bindAll, ma bindAll sta avvolgendo ogni chiamata ai metodi elencati con la contesto dell'oggetto reale, ma questo non può fare nulla se si chiama lo stesso metodo su un altro oggetto :).

Aggiornato

ho leggere di più .. sembra bindAll e il terzo paramater del comando bind fare esattamente lo stesso. Quindi forse puoi usare l'una o l'altra.

Il perché non funziona il bindAll nel model.remove è perché si è dimenticato di aggiungerlo alla linea _.bindAll(this, 'render'), guarda nel codice. E il mio suggerimento l'ha risolto perché, come ho detto, entrambi gli approcci fanno lo stesso.

cosa tutto questo sta facendo è assicurando che le chiamate ai metodi elencati (render, remove, ... in un caso o nell'altro this.remove) sono gonna interpretare this come riferimento all'oggetto effettivo. Questo può sembrare stupido ma this è molto volatile in JS.

Non preoccuparti se sei ancora confuso con la cosa this, ho a che fare con esso per molto tempo e ancora not completely cofindent.

Forse essais like this può aiutarci.

+1

Cosa vuoi dire che ho un problema con ogni definizione di binding evenet? Non sono sicuro di capire davvero che cosa sia il bindall per essere onesto con te. Ho solo pensato che tutti gli eventi dovevano essere aggiunti a bindall. – reach4thelasers

+0

Che cosa rappresenta il terzo parametro sulla funzione di associazione? – reach4thelasers

+0

ha funzionato! Grazie! Pensa di aver scoperto a cosa serve il bindall leggendo un altro post StackOverflow, ma perché non ha funzionato? sembra fare la stessa cosa .... anche perché non ho bisogno di un extra "this" sull'estratto conto della collezione? – reach4thelasers

-1

I metodi di rimozione su entrambe le viste vengono probabilmente chiamati perché si è deciso di rimuovere sia sul modello che sulla raccolta.

In RosterEntry:

this.model.bind('remove', this.remove); 

in roster:

this.collection.bind('remove', this.remove); 
+0

Non è questo quello che ho già? – reach4thelasers

0

Hai provato quanto segue?

this.listenTo(this.model, "remove", this.remove); 

che sembra funzionare per me e mi piace il modo in cui si legge un po 'meglio.

Link to Backbone doc

Problemi correlati