I’m attempting to use Backbone.js to simplify data (JSON) management and interaction with DOM.
Firstly, I’m not sure if Backbone.js can indeed simplify and improve the current process, but I’d like to assume it can.
Previously I’m retrieving the data with jQuery AJAX function. Now, I’m retrieving the data(still with AJAX) Backbone style into the Backbone model.
For update, previously I was parsing through the JSON object itself to update data. I would then send back the updated json to the back-end (just as I’ve received it).
Now, is it possible to use the set function in Backbone to simplify something like the below and ideally where should the set attribute behaviour (and all other UI bindings like change events) be constructed? Would it be on the fetch() success handler, which is in the View initializer?
function setBucketOffer(bucketName, newId) {
var segments = json.segments;
for (var i = 0; i < segments.length; i++) {
if (segments[i].market.toLowerCase() === g_market) {
var genders = segments[i].gender;
for (var i = 0; i < genders.length; i++) {
if (genders[i].name.toLowerCase() === g_segment) {
var buckets = genders[i].buckets;
for (var i = 0; i < buckets.length; i++) {
if (buckets[i].name === bucketName) {
buckets[i].confirm = newId;
return;
}
}
}
}
}
}
}
Example JSON
{
"segments": [
{
"market": "Market1",
"gender": [
{
"name": "male",
"buckets": [
{
"name": "Market1_M_CBD",
"subscribers": "50,000",
"postcode": "20000-2010",
"lastsend": "13/03/12 4:30PM",
"suggest": "10054",
"confirm": ""
},
{
"name": "Market1_M_North",
"subscribers": "50,000",
"postcode": "20000-2010",
"lastsend": "13/03/12 4:30PM",
"suggest": "10054",
"confirm": ""
}
]
},
{
"name": "female",
"buckets": [
{
"name": "Market1_F_CBD",
"subscribers": "50,000",
"postcode": "20000-2010",
"lastsend": "13/03/12 4:30PM",
"suggest": "10054",
"confirm": "10054"
}
]
}
]
},
{
"market": "Market2",
"gender": [
{
"name": "male",
"buckets": [
{
"name": "Market2_M_CBD",
"subscribers": "50,000",
"postcode": "20000-2010",
"lastsend": "13/03/12 4:30PM",
"suggest": "10054",
"confirm": "10054"
},
{
"name": "Market2_M_North",
"subscribers": "50,000",
"postcode": "20000-2010",
"lastsend": "13/03/12 4:30PM",
"suggest": "10054",
"confirm": "10054"
},
{
"name": "Market2_M_South",
"subscribers": "50,000",
"postcode": "20000-2010",
"lastsend": "13/03/12 4:30PM",
"suggest": "10054",
"confirm": "10054"
}
]
}
]
}
]
}
Edit 1
From here, I’m trying to make good use of Parse and to get just segments from my JSON:
var Offers = Backbone.Collection.extend({
url: 'URL',
parse: function (response) {
return response.segments;
}
});
Here, I’m getting more than just response.segments. Also not sure if it’s right for me to use the render function or fetch success function to populate the DOM. Suppose I have my html template in the DOM… I want to clone it using jQuery clone() and populate the clone using a forEach on segments, and push back all the clones into the html body. Is this workable in backbone, how would you do it? (I’m able to do this without backbone.js, but would like to see how I can improve with backbone.js, and bind all the data on the clones to model changes)
var OfferView = Backbone.View.extend({
initialize: function () {
this.model = new Offers();
this.model.fetch({
success: function (collection, response) {
console.log(response);
}
});
this.model.on('change', this.modelChange);
this.model.on('change', this.render);
this.modelChange = function () {
alert('model changed');
};
},
render: function () {
}
});
Edit 2
I’m up to creating individual views through a forEach but am having trouble inserting these back into the DOM. What am I doing wrong? (Not sure around the return this part)
// DEFINE VIEW
var OfferView = Backbone.View.extend({
initialize: function () {
this.model = new Offers();
this.model.fetch();
this.model.on('change', this.modelChange);
this.model.on('change', this.render);
this.modelChange = function () {
alert('model changed');
};
this.render();
},
render: function () {
var self = this;
this.model.forEach(function (s) {
var view = new OfferMarketView({
id: "container" + s.get('name').toLowerCase().replace(/\s*/g, '')
});
$('#leftCol').append(view.el);
});
return this;
}
});
var OfferMarketView = Backbone.View.extend({
tagName: "div",
className: "marketContainer",
events: {},
render: function() {
}
});
Whenever you call fetch on a model the response is passed through a
parsemethod that can be defined in your model.parsetakes one parameter, the ajax response:In that function you can do whatever you want with the data that comes back from your ajax request and eventually return that object. The object returned by the parse method will be set on your model.
For event binding, you’ll want to do that in your view. In the initialize method of your view you can do something like:
Now, any time something causes that model to trigger its change event
someFunction( also defined in your view ) will run.EDIT
The sample json you added to the question looks to be pretty normalized. With that data, I’d be fetching it into a collection. If that’s the structure you want your models to look like then you don’t need to do much parsing.
in you collection file if you create a parse method that does the following:
When you call your fetch,
this.collection.fetch()on a successful request, your collection will be filled with models that contain attributes in a structure that matches your response.EDIT 2
Your binding looks ok.
in this section of code:
The parameters that are passed back on a success in a collection fetch are
(collection, response)collectionis the result of collection call and whatthis.collectionwill end up being.responseis the response of your ajax request.I’m not sure what
initAll(attributes)is supposed to be doing. If you add a parse method like I posted above, your collection will contain a set of models with the attributes of each segment.Also, rather than calling
this.render()at the end, you could do bind render to the change event:That way any time your collection changes, that view will automatically render again so your changes will show up.