2011-07-13 20 views
7

Tengo problemas para eliminar un elemento de una colección dentro de un modelo cuando estoy en una vista. Básicamente la estructura del modelo/colección es la siguiente:Colección backbone.js que no elimina correctamente el elemento a la vista

enter image description here

básicamente al intentar eliminar un elemento de la colección subtema en el subelemento ver que en realidad elimina el elemento correcto de la colección. Sin embargo, cuando persista el modelo principal, el elemento parece estar todavía en la colección.
Esta es la forma en que se estructuran mis puntos de vista:

enter image description here

La vista principal inserta los nodos DOM requeridos por el modelo principal, y les principal modelo crea una nueva vista para el modelo artículo etc. Todos los puntos de vista son conseguir el modelo principal como opción de modelo de este modo:

new App.Views.MainModelView({ 
    model : this.model, 
    el : $('#nodeID') 
}) 

la única diferencia está en la creación de la vista del modelo Subelemento, donde, debido a la re usabilidad de la vista y la plantilla, todavía pase en el principal modelo, sin embargo, también paso en el elemento en la colección de elementos que es cur está siendo modificado. Que se parece a esto:

new App.Views.ItemView({ 
    model : this.model, 
    item : this.selectedItem, 
    el : $('#nodeID') 
}); 

En el método vista de inicio del subtema hago lo siguiente:

this.item = (this.options.item) ? this.options.item : this.model; 

Para extraer un sub-elemento de la colección subtema que hago:

removeSubItem : function(e) { 
    // get the id of the sub-item to be removed 
    var id = $(e.target).closest('tr').attr('data-id'); 
    if (!id) throw "Could not retrieve data id"; 
    // retrieve the sub-item from the collection 
    var subItem = this.item.subItems.get(id); 
    // remove the sub-item from the collection 
    this.item.subItems.remove(subItem); 
}, 

Como dije anteriormente cuando eliminé el subartículo e inspeccioné la colección modificada por la vista, puedo ver que el subartículo ha sido eliminado de la colección, sin embargo, entonces persisto el modelo principal, el subconjunto eliminado el artículo vuelve a aparecer. Esto me lleva a pensar que, en algún momento, la colección de subtemas podría clonarse, lo que podría explicar la repentina reaparición del subtema.

Sé que este es un problema bastante específico y no estoy seguro de si es posible llegar a la causa del problema con lo que he proporcionado aquí, si necesita más información, por favor hágamelo saber.

Gracias por toda su ayuda,

Vincent

========== ============ EDITAR

Para responder a algunas de las preguntas a continuación me permiten describir el alcance en el que estoy experimentando este problema:

Si la consola registra la colección this.item.subItems en la vista SubItem, después de llamar a RemoveSubItem, puedo ver que la instancia del SubItem modelo ha sido eliminado con éxito. Antes de llamar al método guardar en el modelo principal, la consola registra el retorno de la función toJSON. En este punto, estoy experimentando el problema de que la instancia eliminada anteriormente está 'atrás' en la colección. He estado monitoreando el tráfico entre el cliente y el servidor con Wireshark y la consola de desarrolladores de Google Chrome, y no hay llamadas al servidor para actualizar ninguno de los modelos.

El método toJSON para la recogida SubItem se parece a esto:

toJSON : function() { 
    App.log(["SubItem::collection::toJSON", this], "info"); 
    var json = {}; 
    // make sure the key for each SubItem is the primary key 
    this.each(function(subItem) { 
    json[subItem.get('id')] = subItem.toJSON(); 
    }); 

    return json; 
} 
+0

Por favor explíquenos o muéstrenos qué quiere decir con "persistir" y cómo lo hace y cómo lo recarga. – Julien

+0

Cuando hablo de persistencia, me refiero a guardar los modelos en el servidor, llamando así al método de guardar en el modelo principal. El guardado se realiza a través de una serie de métodos toJSON nativos o reemplazados. Por favor, mira la edición para más información. – luxerama

Respuesta

2

Backbone.js apoyo para la recolección anidada/modelos es no- existentes, y no proporcionan soporte de guardado (ver http://documentcloud.github.com/backbone/#FAQ-nested). Debe sobrescribir toJSON en cualquier modelo con una subcolección. Me he encontrado con este escenario un millón de veces. Si usted tiene algo así como (en CoffeeScript):

class MainModel extends Backbone.Model 

    itemCollection: -> 
     @_itemCollection ?= new ItemCollection(@get('itemCollection')) 


class ItemCollection extends Backbone.Collection 

    model: ItemModel 


class ItemModel extends Backbone.Model 

    subCollection: -> 
     @_subCollection ?= new SubCollection(@get('subCollection')) 


class SubCollection extends Backbone.Collection 

    model: SubModel 


class SubModel extends Backbone.Model 


mainModel = new MainModel(json) 

A continuación, con el fin de mainModel.save() para trabajar, es necesario anular toJSON en MainModel y ItemModel, como:

class MainModel extends Backbone.Model 

    itemCollection: -> 
     @_itemCollection ?= new ItemCollection(@get('itemCollection')) 

    toJSON: -> 
     return _.extend(@attributes, {itemCollection: @itemCollection().toJSON()}) 


class ItemModel extends Backbone.Model 

    subCollection: -> 
     @_subCollection ?= new SubCollection(@get('subCollection')) 

    toJSON: -> 
     return _.extend(@attributes, {subCollection: @subCollection().toJSON()}) 

escribí el ejemplo en coffeescript porque es mucho más conciso que javascript. Si necesita ayuda para encontrarle sentido, solo pregunte.

Espero que esto ayude!

--- --- Nota

Técnicamente, en CoffeeScript, los métodos toJSON podría ser simplemente:

toJSON: -> 
    _.extend @attributes, itemCollection: @itemCollection().toJSON() 

Pero lo escribí como lo hice para ser más comprensible para los no coffeescripters .

1

Sin mirar a su base de código entero que cree que puede tener la estructura de un poco mal. Normalmente con la columna vertebral casi nunca paso el elemento: el directamente a la vista. La vista es responsable de generar su propio el. Después de que se ha procesado, inserto el nuevo view.el en el DOM. Como debajo de

var subView = new FooView({ model: fooModel }); 

mainView.$(".list").append(subView.el); 

En el caso anterior, hay un objeto principal con cada subvista. Si necesita eliminar la subvista no necesita hacer una consulta de selector para encontrarla, simplemente llame al el método de eliminación en el objeto y sepa cómo eliminarlo del dom.

O, para ser más específicos Subvista maneja un evento click sobre sí misma la que entonces puede manejar mediante la destrucción que está asociado modelo y luego llamar a eliminar sobre sí mismo

Cuestiones relacionadas