2011-07-06 11 views
16

Supongo que esto es un error en mi código o una característica no documentada (en la medida en que pude encontrar) de backbone.js. Cuando creé mi colección y mi vista, ya existe un modelo en esa colección que no creé, o supongo que no lo hice debido a la identificación no definida. A continuación está mi código.La colección backbone.js agrega un elemento vacío cuando se crea?

// ---------------------------------------------------------- Work Order 
window.WO = Backbone.Model.extend({ 
    default: { 
     wonum: null, 
     part: null, 
     desc: null, 
     comment: null, 
     order: null, 
     section: null 
    }, 
    url: "/rest/wo/" 
}); 
window.WOView = Backbone.View.extend({ 
    tagName: "tr", 
    className: "wo", 
    events: { 
     "keypress .woComment"  : "updateOnEnter" 
    }, 
    initialize: function(options) 
    { 
     _.bindAll(this, 'render', 'close', 'updateOnEnter'); 
     this.render = _.bind(this.render, this); 
     this.model.bind('change', this.render); 
    }, 
    render: function() 
    { 
     $(this.el).html(this.woTemplate(this.model.toJSON())); 
     this.input = this.$('.woComment'); 
     this.input.bind('blur', this.close); 
     return this; 
    }, 
    woTemplate: _.template($('#woTemplate').html()), 
    close: function() 
    { 
     this.model.set({comment: this.input.val()}); 
     this.model.save({},{contentType: 'application/jason'}); 
    }, 
    updateOnEnter: function(e) { 
     if (e.keyCode == 13) this.close(); 
    } 
}); 
// ------------------------------------------------------------- Section 
window.SectionC = Backbone.Collection.extend({ 
    comparator: function(woObj) 
    { 
     return woObj.get('order'); 
    } 
}); 
window.Section = Backbone.Model.extend({ 
    defaults: { 
     id: null, 
     name: null 
    }, 
    events: { 
     'update' : 'doOrder', 
     'change' : 'doOrder' 
    }, 
    url: "/rest/section", 
    woc: null, 
    initialize: function() 
    { 
     this.woc = new SectionC({model: window.WO}); 
    }, 
    add: function(woObj) 
    { 
     this.woc.add(woObj); 
     this.doOrder(); 
    }, 
    doOrder: function() 
    { 
     console.log("Calling doOrder"); 
     var that = this; 
     var sel = "#sec"+this.get('id')+" .wo"; 
     $(sel).each(function(i,elem) 
     { 
      var elemID = $(elem).attr('id'); 
      var woObj = that.woc.get(elemID); 
      woObj.set({order: i}); 
     }); 
    }, 
}); 

window.SectionView = Backbone.View.extend({ 
    tagName: "table", 
    className: "section", 
    initialize: function() 
    { 
     _(this).bindAll('add','remove','change'); 
     this.render = _.bind(this.render, this); 
     this.mySort = _.bind(this.mySort, this); 
    }, 
    sectionTemplate: _.template($('#sectionTemplate').html()), 
    render: function() 
    { 
     this._rendered = true; 
     var that = this; 
     $(this.el).empty(); 
     $(this.el).attr('id',"sec"+this.model.get('id')); 
     var woData = null; 
     _(this.models).each(function(woObj) 
     { 
      var wov = new WOView({ 
       model: woObj, 
       id: woObj.get('wonum')}); 
      woData += wov.render().el; 
     }); 
     $(this.el).html(this.sectionTemplate({woData: woData})); 
     return this; 
    }, 
    add: function(woObj) 
    { 
     woObj.set({section: this.model.id, id: woObj.get('wonum')}); 
     this.model.add(woObj); 
     if(this._rendered) 
     { 
      var wov = new WOView({ 
       model: woObj, 
       id: woObj.get('wonum')}); 
      $(this.el).append(wov.render().el); 
     } 
     //this.mySort(); 
    }, 
    change: function() 
    { 
     this.render(); 
    }, 
    mySort: function() 
    { 
     var that = this; 
     var sel = "#sec"+this.model.get('id')+" .wo"; 
     $(sel).each(function(i,elem) 
     { 
      var elemID = $(elem).attr('id'); 
      var woObj = that.model.woc.get(elemID); 
      woObj.set({order: i}); 
     }); 
    }, 
    saveSection: function() 
    { 
     var json = {}; 
     json.section = this.model.get('id'); 
     json.order = {}; 
     var sel = "#sec"+this.model.get('id')+" .wo"; 
     $(sel).each(function(i,elem) 
     { 
      json.order[i] = $(elem).attr('id'); 
     }); 
     console.log(json); 
     _(this.model.woc.models).each(function(woObj) 
     { 
      if(woObj.get('id') != "" && woObj.get('id') != undefined) 
       woObj.save(); 
     }); 
    } 
}); 
// ---------------------------------------------------------------- Page 
window.PageC = Backbone.Collection.extend({ 
    comparator: function(obj) 
    { 
     return obj.get('order'); 
    } 
}); 

window.PageView = Backbone.View.extend({ 
    tagName: "div", 
    className: "prodSchedPage", 
    initialize: function() 
    { 
     _(this).bindAll('add'); 
     this.render = _.bind(this.render, this); 
    }, 
    render: function() 
    { 
     var that = this; 
     this._rendered = true; 
     $(this.el).empty(); 
     // Loop through the sections and render them 
     _(this.collection.models).each(function(secObj) 
     { 
      var v = new SectionView({model: secObj, id: secObj.get('id')}); 
      $(that.el).append(v.render().el); 
     }); 
     return this; 
    }, 
    add: function(sectionObj) 
    { 
     this.collection.add(sectionObj); 
     if(this._rendered) 
     { 
      this.render(); 
     } 
    }, 
    addSection: function(sectionObj){this.add(sectionObj);}, 
    addWO: function(secID,woObj) 
    { 
     var secObj = this.collection.get(secID); 
     if(secID = undefined) 
     { 
      alert("Error: Section does not exist!"); 
      return; 
     } 
     secObj.add(woObj); 
    } 
}); 

window.PSPage = new window.PageC({}); 
window.PSPV = new window.PageView({collection: window.PSPage}); 
$("body").append(window.PSPV.render().el); 
//window.PSPV.add(new Section({id: 1, name: "Section 1"})); 

Respuesta

33

Cuando crea una instancia de la colección, el primer argumento es una matriz de modelos, el segundo argumento son las opciones.

window.PSPage = new window.PageC({}); 

Cuando se pasa en {} el constructor pasa los argumentos a través del método de restablecimiento al método add y los de los controles método Add para ver si el argumento es una matriz y cuando no una matriz agrega {} como modelo singular. El método add en el backbone 0.5.1 está aquí (0.3.3 funciones de la misma manera):

add: function(models, options) { 

    if (_.isArray(models)) { 
    for (var i = 0, l = models.length; i < l; i++) { 
     this._add(models[i], options); 
    } 
    } else { 
    this._add(models, options); 
    } 
    return this; 
}, 

Si usted no pasa ningún argumento para el constructor, usted debe comenzar con una colección vacía.

window.PSPage = new window.PageC(); 
+0

Gracias. Sabía que debía haber algo que me estaba perdiendo. – Jason

+0

de nada. – c3rin

+2

Hmm ... entonces, si tiene un método constructor, ¿cuál sería la mejor manera de evitar que se cree un objeto nulo? – Trip

3

Me encontré con el mismo problema porque necesitaba pasar argumentos al constructor de mi colección. Si miro en mi instancia de colección, dice que hay cero modelos, pero si repito usando cada uno(), encuentra ese modelo fantasma que no creé.

Según la respuesta aceptada volví y volví a mirar la API here.

Mi código ahora se ve así, y parece que para evitar este problema:

var myCollection = new MyCollection(new Array(), { 
    setting1: "foo", 
    setting2: "bar" 
}); 
1

De la documentación columna vertebral de constructor/inicializar las colecciones:

new Backbone.Collection([models], [options]) 

Esto quiere decir, que cuando se quiere para crear una nueva colección vacía con algunas opciones, realmente debes llamar al constructor con el primer argumento para que sea una matriz vacía, no tu objeto de opciones (simplifico un código bit @killthrush para que no digas 'nueva matriz()' y uses [] en su lugar):

var myCollection = new MyCollection([], { 
    setting1: "foo", 
    setting2: "bar" 
}); 

Ahora, en la definición de colección, usted debe tener algo como para poder acceder a las opciones de objeto:

var myCollection = Backbone.Collection.extend({ 
    // add model, url, etc here 
    initialize: function (models, options) { 
     // use options here, e.g. 
     this.setting1 = options.setting1; 
     this.setting2 = options.setting2; 
    } 
}); 
Cuestiones relacionadas