2012-04-16 31 views
5

Estoy usando backbone.js para implementar una lista de amigos también conocida como Lista. Mi opinión columna vertebral de la colección Lista e individual rosterEntry son los siguientes:Backbone.js: Eliminar un elemento de una colección

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

estoy probando por ahora el uso de la consola de Firebug y pueden poblar la plantilla bien ejecutando el siguiente:

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

añadir a una colección también funciona bien, ejecutando el siguiente en la consola de Firebug:

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

y se agrega el nuevo rosterEntry a la lista.

Mi problema es que collection.remove(5) se elimina de la colección en memoria, pero no hace nada para actualizar el DOM.

Extrañamente, si omito la función remove() desde la Vista de lista, se eliminan todas las entradas en la lista. Si agrego este método con nada más que un registro de la consola, se llama el método de eliminación tanto en la lista como en las visitas de RosterEntry, aunque no estoy seguro de por qué, pero están fuera de servicio.

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

si elimino la función de eliminación del modelo RosterEntry me sale este error:

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

¿Qué estoy haciendo mal? ¿Cómo elimino el elemento del DOM cuando se elimina de la colección?

Respuesta

2

yo creo que hay un problema con el context en cada definición de evento se unen.

tratar de cambiar esto:

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

Por esta:

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

Sé que usted ha tratado de resolver esto con el bindAll, pero bindAll está envolviendo cada llamada a los métodos que se indican con la contexto del objeto real, pero esto no puede hacer nada si llama al mismo método en otro objeto :).

Actualizado

he leer más .. parece bindAll y el tercer parámetro de comando de la bind hacer exactamente lo mismo. Entonces quizás puedas usar el uno o el otro.

El porque no está funcionando el bindAll en el model.remove es porque se le olvidó añadir a la línea de _.bindAll(this, 'render'), busque en su código. Y mi sugerencia lo solucionó porque, como digo, ambos enfoques hacen lo mismo.

Lo que todo esto está haciendo es asegurar que las llamadas a los métodos enumerados (render, remove, ... en un caso o en el otro this.remove) son interpretadas va this como una referencia al objeto real. Esto puede parecer estúpido, pero this es muy volátil en JS.

No se preocupe si todavía está confundido con la cosa this, tengo que lidiar con ella por mucho tiempo y todavía not completely cofindent.

Tal vez essais like this nos puede ayudar.

+1

¿Qué quiere decir que tengo un problema con cada definición de vinculación de evenet? No estoy seguro de entender realmente qué es Bindall para ser honesto con usted. Solo pensé que todos los eventos tenían que ser agregados a Bindall. – reach4thelasers

+0

¿Qué representa el tercer parámetro en la función de vinculación? – reach4thelasers

+0

esto funcionó! ¡Gracias! Creo que he averiguado para qué sirve Bindall al leer otra publicación de stackoverflow, pero ¿por qué no funcionó? parece hacer lo mismo ... también ¿por qué no necesito un "esto" extra en la declaración de vinculación de la colección? – reach4thelasers

-1

Probablemente se estén llamando a los métodos de eliminación en ambas vistas porque debe eliminar tanto en el modelo como en la colección.

En RosterEntry:

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

En Lista:

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

¿No es esto lo que ya tengo? – reach4thelasers

0

¿Ha intentado lo siguiente?

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

Eso parece funcionar para mí y me gusta la forma en que se lee un poco mejor.

Link to Backbone doc

Cuestiones relacionadas