Backbone collection different result strategy - backbone.js

Lets say I have method that returns from server 2 data sets:
On success:
{"status":true,"data":[{"id":1, "name": "yolo"}, {"id":2, "name": "yolo2"}]}
On fail:
{"status":false,"data":["Some error"]}
I use following collection:
var Entities.Collection = Backbone.Collection.extend({
url: "/entity",
model: Entities.Model,
parse: function(json) {
// return different data ?
// trigger something ?
return json.data;
}
});
The problem is when I have fail result after fetch it will set collection with error details.
What is the best practice to handle such issue ?

I'd say populate the collection only if you have a success scenario, which would look something like this:
var Entities.Collection = Backbone.Collection.extend({
url: "/entity",
model: Entities.Model,
parse: function(response) {
if(response.status)
return response.data;
else {} // handle this if you want to do something like triggering an event or
// setting a flag, else leave it
}
});

Related

Backbone.js Work with server response to save() method

I'm kind of new to Backbone. I need use the data in the server response to a save() method but I'm not sure how to get it. This is the code:
$(".act_btn").on("click", function(){
var act_id = $(this).attr("data-id");
startRecordItem = new StartRecordItem({
activity: act_id,
});
startRecordItem.save({
success: function(response){console.log(response)}
});
/*
recordItem = new RecordItem({
id: ... <---- I have to populate this with the data from the server response.
});
*/
Right now the success function doesn't work at all, what am I missing? I'd like to get an attribute from the JSON response and then use it on the ´new RecordItem´. The save itself works correctly and the response looks like this:
{"activity": 1, "id": 14}
What you're missing is that the first argument of .save. is the attributes that get passed into the model, pre-save. You want to do something more like this:
startRecordItem.save(null, {
success: function(response) {
console.log(response);
}
});
Since Backbone fires a sync event on successful save, you could also do this:
this.listenTo(startRecordItem, 'sync', function() { /* logic here */ });

Backbone fetch single model attributes

im trying to fetch a single Models attributes. I use this model as kind of a config file for an app im currently building. But i cant get my head around how to get the attributes in a nice way.
The model looks like this:
WelcomeModel = Backbone.Model.extend({
url: "assets/json/config.json",
parse: function (response) {
return response.data;
}
});
The json looks liks this:
{
"data": [{
"companyName": "lorem ipsum",
"companyLogo": "loremipsum.png"
}]
}
And in my view i fetch it like this.
this.model = new WelcomeModel();
this.model.fetch({
success: function(model,response) {
console.log(model);
},
error: function() {
console.log('error')
}
});
1) parse method returns array instead object. Replace
return response.data
with
return response.data[0];
2) add defaults hash to your WelcomeModel model.
defaults: {
companyName: '',
companyLogo: ''
}

Overrriding collection fetch() method in Backbone.js is causing a double request to the server

I'm doing an application with Backbone.js and Require.js. I have an "Opportunities" Backbone collection and I needed to modify the fetch method because the data from the server comes inside a "results" object.
I did the trick by doing something I found in this question, at this point all looks good.
The problem is that I noticed that the fetch method is asking the server for the data TWO TIMES and not ONE as expected.
I am testing and now I found that if I remove this code: return Backbone.Collection.prototype.fetch.call(this, options); Backbone asks the url for the data only one time, obviously this code is causing the problem but I don't know the reason.
This is my Backbone collection
define([
'backbone',
'models/Opportunity'
], function(Backbone, Opportunity){
var Opportunities = Backbone.Collection.extend({
url: "/api/v1/opps/",
model: Opportunity,
// Need to have custom fetch because json data is coming inside a
// "results" array inside the JSON.
fetch : function(options) {
// store reference for this collection
var collection = this;
$.ajax({
type : 'GET',
url : this.url,
dataType : 'json',
success : function(data) {
// set collection main data
collection.reset(data.results);
}
});
// For some reason this is causing a double request
// to the server
return Backbone.Collection.prototype.fetch.call(this, options);
}
});
return Opportunities;
});
Someone knows the reason because this error is happening?
It's fetching it twice because you're using jQuery to fetch it directly, the calling the models own fetch method which will call an AJAX request as well.
If you want to return data.results back to your collection (and subsequently models), you can use the parse method, like:
var Opportunities = Backbone.Collection.extend({
url: "/api/v1/opps/",
model: Opportunity,
parse: function(data){
return data.results;
}
});

Setting Default Options for Backbone Collections

I have a Backbone Collection like so:
var ThreadCollection = Backbone.Collection.extend({
url: '/api/rest/thread/getList'
});
var myCollection = new ThreadCollection();
And then I'm fetching it from the server using the data object to append the query parameters (so in this case it comes out '/api/rest/thread/getList?userId=487343')
myCollection.fetch({
data: {
userId: 487343
}
})
There are other parameters that I may want to use instead of userId (groupId, orgId, etc) but I'd ideally define the data parameters upon initialization and from then on be able to run fetch() without specifying. Something like this:
var myCollection = new ThreadCollection({
data: {
userId: 487343
}
});
myCollection.fetch()
but it doesn't work. Does anyone know if there's a way to do this? Thanks!
One way is to define a custom fetch method on your collection which calls the super fetch method with some overridable defaults:
var ThreadCollection = Backbone.Collection.extend({
url: '/api/rest/thread/getList',
fetch: function(options) {
return Backbone.Collection.prototype.fetch.call(this, _.extend({
data: {
userId: 48743
}
}, options));
}
});
var myCollection = new ThreadCollection();
myCollection.fetch();

Wrapping my head around a unique backbone.js collection

I'm working out my first backbone.js app and have run into a bit of a wall. Perhaps someone can help me past this hurdle (gap in my understanding). What I want/need to do is to return the collection data to my router, so I can bind it to a Kendo UI Grid, but I'm not seeing any of the search results in my collection... I figure I must be missing something fundamental, but I'm not sure what it is.
Here is what I have so far:
ES.Router = Backbone.Router.extend({routes: {
'': 'search',
'search': 'search',
'results': 'results'
},
results: function() {
var resultsData = new ES.Results();
var boo = resultsData.fetch({
data: JSON.stringify({"query":"myquery"}),
type: 'POST',
contentType: 'application/json'
});
console.log(boo);
}});
ES.Result = Backbone.Model.extend();
ES.Results = Backbone.Collection.extend({
model: ES.Result,
url: '/search/query'
});
There are a few issues here:
A fetch should be a GET, not a POST, because a fetch should not save or modify anything
Maybe just a personal preference, but I'd url as a function, so as to avoid trying to modify the AJAX request options manually.
The fetch call will always be asynchronous, so you need to either add a success callback in the options hash, or add a listener to the collection's reset event
I'd write the collection like this:
ES.Results = Backbone.Collection.extend({
initialize: function() {
this.query = "test";
},
model: ES.Result,
url: function() {
return '/search/query?query=' + this.query;
}
});
Then set the search when you create the collection:
var resultsData = new ES.Results();
resultsData.query = "soccer";
And use success and/or the on("reset") event to handle the result:
resultsData.on("reset", function(collection) {
console.log(collection);
});
console.log("Fetching....");
resultsData.fetch({
success: function(collection, response) {
console.log("Got data!" + collection.length);
},
error: function(collection, response) {
console.log("Error: " + response.responseText);
}
});
​

Resources