Last active
December 18, 2015 17:59
-
-
Save jdkanani/5822296 to your computer and use it in GitHub Desktop.
This example demonstrates how to incrementally load and save object graphs using Backbone-associations. This is important because rarely, there would be a need to fetch (or save) a entire object hierarchy from the server.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var MyApp = { | |
context: {} | |
}; | |
MyApp.context.departments = null; | |
MyApp.context.employees = null; | |
var counter = 100; | |
/** | |
* Initialization of associated models | |
*/ | |
var Location = Backbone.AssociatedModel.extend({ | |
defaults:{ | |
id:-1, | |
add1:"", | |
add2:null, | |
zip:"", | |
state:"" | |
}, | |
urlRoot: '/location' | |
}); | |
var Locations = Backbone.Collection.extend({ | |
model: Location, | |
url: function() { | |
return '/locations'; | |
} | |
}); | |
var Department = Backbone.AssociatedModel.extend({ | |
initialize: function(){ | |
var dept = this; | |
this.get('locations').url = function(){ | |
return '/department/' + dept.id + '/locations'; | |
} | |
}, | |
relations:[ | |
{ | |
type:Backbone.Many, | |
key:'locations', | |
collectionType: Locations | |
} | |
], | |
defaults:{ | |
name:'', | |
number:-1 | |
}, | |
urlRoot: '/department' | |
}); | |
var Departments = Backbone.Collection.extend({ | |
model: Department, | |
comparator: function(d){ | |
return d.get('number'); | |
}, | |
url: '/departments', | |
sync: function(method, collection, options) { | |
return options.success.call(this, [ | |
{id:1, name:"sales", number: 21, locations:[{id:'l1', zip: 94404}]}, | |
{id:2, name:"admin", number: 22, locations:[{id:'l2', zip: 94404}]} | |
], options); | |
} | |
}); | |
// toDepartment - which returns department model object using passed id | |
var toDepartment = function(id) { | |
if (id instanceof Department) return id; | |
if (_.isObject(id)) return id; | |
var deps = MyApp.context.departments; | |
var found = deps && deps.find(function (m) { | |
return m.get(m.idAttribute) === id; | |
}); | |
return found ? found : id; | |
} | |
var Employee = Backbone.AssociatedModel.extend({ | |
relations:[ | |
{ | |
type:Backbone.One, | |
key:'works_for', | |
relatedModel: Department, | |
// property to map work_for to department object | |
// using `idAttribute` | |
map: toDepartment | |
} | |
], | |
defaults: { | |
sex:'M', //{F,M} | |
fname:"", | |
lname:"" | |
}, | |
getName: function() { | |
return this.get('fname') + " " + this.get('lname'); | |
}, | |
urlRoot: '/employee', | |
toJSON: function(){ | |
var department = this.get('works_for'); | |
return { | |
fname: this.get('fname'), | |
lname: this.get('lname'), | |
sex: this.get('sex'), | |
age: this.get('age'), | |
works_for: department && department.get(department.idAttribute) | |
}; | |
}, | |
// For demo purposes only | |
sync: function(method, model, options){ | |
var response = {}; | |
if (method === 'create') { | |
response[model.idAttribute] = counter++; // dummy id | |
} else if(method === 'update'){ | |
// Let's assume that - after success update, server sends model's json object | |
response = model.toJSON(); | |
} | |
return options.success.call(this, response); | |
} | |
}); | |
var Employees = Backbone.Collection.extend({ | |
model: Employee, | |
url: '/employees', | |
comparator: function(e){ | |
return e.get('lname'); | |
}, | |
sync: function(method, c, options) { | |
return options.success.call(this, [ | |
{id: 1, fname:"John", lname:"Doe", works_for: 1}, | |
{id: 2, fname:"Clark", lname:"Kent", works_for: 2} | |
]); | |
} | |
}); | |
/** | |
* Fetch | |
*/ | |
// Create department list | |
var departments = MyApp.context.departments = new Departments(); | |
// Fetch `MyApp.context.departments` | |
departments.fetch(); | |
console.log("MyApp.context.departments : "); | |
console.log(departments); | |
// Create employee list | |
var employees = MyApp.context.employees = new Employees(); | |
employees.on("add", function(newModel, col, options){ | |
console.log("New joinee : '" + newModel.getName() + "'(id: "+ newModel.get('id') +")"); | |
}); | |
// Fetch `MyApp.context.employees` | |
employees.fetch(); | |
console.log("MyApp.context.employees : "); | |
console.log(employees); | |
// Fetch locations | |
var dep1 = departments.at(0); | |
dep1.get('locations').fetch(); // 404. Because no server simulation for this service | |
/** | |
* Save | |
*/ | |
var emp1 = employees.at(0); | |
var emp2 = employees.at(1); | |
// Create new employee for department 'admin' | |
var newEmp = new Employee({fname: 'Will', lname: 'Smith', works_for: 2}); | |
newEmp.save(); | |
console.log("New employee :"); | |
console.log(newEmp); | |
// Add `newEmp` to MyApp.context.employees | |
employees.add(newEmp); | |
// Change and save employee's property | |
// will cause update on server | |
newEmp.save({'age': 25}); | |
emp2.save({works_for: 1}); | |
console.log("Emp2: "); | |
console.log(emp2); |
there's an updated version of the jsfiddle here
Basically, the location of the underscore.js dependency was updated.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
You can execute and play with this gist here.