I am assuming this is either a bug in my code or an undocumented (as far as I could find) feature of backbone.js. When I created my collection and my view there is already a model in that collection that I did not create, or I assume I did not create due to the undefined id. Below is my code.
// ---------------------------------------------------------- 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"}));
When you instantiate the collection, the first argument is an array of models, the second argument is options.
When you pass in {} the constructor passes the arguments through the reset method to the add method and the the add method checks to see if the argument is an array and when not an array adds {} as a singular model. The add method in backbone 0.5.1 is here (0.3.3 functions the same way):
If you don’t pass any arguments to the constructor, you should start with an empty collection.