BackboneJS .fetch() put one object from response in collection - backbone.js

My server response is having two objects (picture):
How can i put just secound object members (models) in my Backbone Collection. I am using collection.fetch to get data from server. Can I somehowe addapt my server response.

You can do this by overriding the parse method of your collection:
var coll = Backbone.Collection.extend({
parse: function(data){
return data.statuses;
}
});
Your Collection will contain what you return from your parse function, in this case you reduce it to the statuses array from your server response.

use parse()
see:
http://backbonejs.org/#Collection-parse
in your collection:
yourCollection = Backbone.Collection.extend({
//other collection stuff.
parse: function(response) {
//save the search metadata in case you need it later
this.search_meatadata = response["search_metadata"];
// return the array of objects.
return response["statuses"];
}
});

Related

Backbone collection different result strategy

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
}
});

backbone parse return results array

The restful api im calling wraps the desired payload (of models) within 'Payload'
I can ONLY get it to work this way, by 1. adding each into this.add(model) and 2. returning the array
Note: 'this' is a Backbone Collection
parse: function(resp, xhr) {
var that = this;
var ourPayload = resp.Payload;
ourPayload.forEach( function(model) { that.add(model);} );
return ourPayload;
},
In all examples I'd expect to simply do
parse: function(resp, xhr) {
return resp.Payload;
}
The format of the rest api is "{"Success":"true", ...., "Payload":[{model},{model},{model}], .... }
Can one explain the need to the collection.add(model)
The problem is that during a Collection fetch each Model's parse will also be called if they are defined. And likely the model's parse function will be defined in just this case: the RESTful API format is using a wrapper around the payload.
Backbone docs
After fetching a model or a collection, all defined parse functions
will now be run. So fetching a collection and getting back new models
could cause both the collection to parse the list, and then each model
to be parsed in turn, if you have both functions defined.
Therefore you need to define a parse as below. Note that 'Payload' is the name of your wrapper, be it payload, data, results,,
// Within a collection, it will not.
parse: function (response, xhr) {
if (_.isObject(response.Payload)) {
return response.Payload;
} else {
return response;
}
}
Now that clue came from nikoshr in this SO answer
Further in some cases, when your entrepid backend guy has wrapped a Model in an array then you gotta do the following with the Payload index [0]
parse: function (response, xhr) {
if (_.isObject(response.Payload)) {
return response.Payload[0];
} else {
return response;
}
}
This should work (it should be put into the collection):
parse: function (response) {
return response.Payload;
}
See the documentation. The Twitter Search API the doc refers to is documented here. The response you get has basically the same structure: you get an object, with a field containing the array of models. The same technique works well when one calls an ASMX webservice, see the example here.

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();

Retrieving the content of a collection after fetch

I am trying to retrieve my models from the local storage in a collection. I enter into "success" but sometimes my collection is still empty. I thought "success" meant the collection was well fetched.
var self = this;
window.rooms= new Rooms();
window.rooms.localStorage = new Backbone.LocalStorage("rooms-backbone");
window.rooms.fetch({
success: function(model, response, options) {
rooms.each(function(room){
this.template = _.template(tpl.get('RoomView'));
$(self.el).append(this.template(room.toJSON()));
console.log(rooms.toJSON());
console.log(model);
console.log(response);
console.log(options);
});
}
});
How can i populate my UI once i am sure the collection is well filled ?
Thx in advance

Resources