override Backbone's Collection-fetch - javascript

I want to get my collection in a NON-RESTful way, so I decide to override the Collection.fetch with
App.carClc = Backbone.Collection.extend({
model : App.cardModel,
url : 'http://localhost/bbtest/data.php',
fetch : function() {
$.ajax({
type : 'GET',
url : this.url,
success : function(data) {
console.log(data);
}
});
}
});
I don't know how to set my collection to the response. I'm new to BackboneJS, thanks all of you!

If you want to add a custom "decorator" to fetch, but not override it completely, try:
var MyCollection = Backbone.Collection.extend({
//custom methods
fetch: function(options) {
//do specific pre-processing
//Call Backbone's fetch
return Backbone.Collection.prototype.fetch.call(this, options);
}
});
Here, you don't have to roll out your own $.ajax
Also, don't forget the return in the last line if you want to use the jQuery promise returned by Backbone's fetch method.
See http://japhr.blogspot.in/2011/10/overriding-url-and-fetch-in-backbonejs.html for more details.

Backbone collection has two methods to set new data add and reset. Let's say you want to replace all collection data with the incoming data and therefor use the reset:
App.carClc = Backbone.Collection.extend({
model : App.cardModel,
url : 'http://localhost/bbtest/data.php',
fetch : function() {
// store reference for this collection
var collection = this;
$.ajax({
type : 'GET',
url : this.url,
dataType : 'json',
success : function(data) {
console.log(data);
// set collection data (assuming you have retrieved a json object)
collection.reset(data)
}
});
}
})

I am using something like this:
$.when( $.ajax( URL, { dataType: "json" } ) )
.then( $.proxy( function( response ) {
ctx.view.collection.reset( response );
},ctx ) );
The main point beeing I use collection.reset(data) to reinitialize the collection

If you would like to keep fetch "thenable" for promises then you could also do something like this:
fetch: function() {
var self = this,
deferred = new $.Deferred();
$.get(this.url).done(function(data) {
// parse data
self.reset({parsed data});
deferred.resolve(); //pass in anything you want in promise
});
return deferred.promise();
}

If you need to do this for every model and/or collection, override Backbone.ajax.
Overriding Backbone.ajax gives you the request options that would be normally passed to $.ajax. You only need to return the response of $.ajax (or some other Promise) and don't need to worry about setting stuff in the collection/model.

Related

AJAX wrapper for jQuery

I want to make a convenience method for my Ajax calls as it is used extensively in the project.
As of now a typical call in the project looks like this.
$.post(
"url",
{
param1: value1,
param2: value2
},
function (data) {}
);
This call is repeated multiple times in the project with different parameters so I would like to be able to create a function to which I can pass the parameters and it will handle the entire Ajax call without me having to write the code every time.
Expected Output:
var data= {firstName:"John", lastName:"Doe", age:46};
do_ajax_request(data);
The function do_ajax_request in turn contains the actual Ajax code which makes the actual request and handles the result.
If possible I would also like for it to return a callback in case I need to perform any extra operations, would a promise work for that?
This would be a global function so I can access it from any JavaScript file.
So many complicated answers for something jQuery supports out of the box. Turning my comment to an answer.
You are basically just coding a wrapper for a wrapper so you do no have to recode some basic lines. No harm in that since it is easy to make the change in one place vs many.
So defined your function and just return the Ajax object that jQuery has. You can than use the done, fail, always methods.
function do_ajax_request (data) {
return $.post("url", data);
}
do_ajax_request({"foo":"bar"})
.done( function(){})
.fail(function(){})
do_ajax_request({"foo":"bar"})
.done( function(){})
.fail(function(){})
If you want to have common code inside, you can do that too, basic idea for an error handler...
function do_ajax_request (data) {
var xhr = $.post("url", data);
xhr.fail(function () {
console.log(arguments)
});
return xhr;
}
I have written several jQuery plug-ins for use in my projects, and have brought along my ajax call method in nearly everyone. Here is a snippet of it from one of my projects. Enjoy!
Method Signature:
obj = An object you want to pass to the ajax call in the data parameter. Pass null if not needed.
method = ajax methods: POST, GET, PUT, DELETE, etc. Default is GET.
endPoint = Url to call.
returnType = html, json, text, etc.
success = callback method when the call is successful.
beforesend = method to call before the send. This is useful when you need to set headers before a call.
failure = callback method when the call is unsuccessul.
var _api = {
call: function (obj, method, endPoint, returnType, success, beforesend, failure) {
obj = obj === null || undefined ? {} : obj;
$.ajax({
method: method || 'GET',
data: !$.isEmptyObject(obj) ? JSON.stringify(obj) : null,
contentType: function () {
switch (returnType) {
case 'json':
return 'application/json';
case 'text':
return 'text/plain';
case 'buffer':
return 'arraybuffer';
case 'html':
default:
return 'text/html';
}
}(returnType === 'json' ? 'application/json; charset=utf-8' : ''),
url: endPoint,
dataType: returnType,
beforeSend: function (xhr, obj) {
if (beforesend) {
beforesend(xhr, obj);
} else {
_api.showLoader();
}
}
}).done(function (data, textStatus, xhr) {
if (success) success(data)
}).fail(function (data, textStatus, xhr) {
if (failure) failure()
}).always(function () {
// Implement code here that you want to run whenever the call is complete regardless of success or failure.
});
}
}
You could create a prototype to with a constructor to handle the input - make the request and handle the response:
ajax.requests = function ( data ) {
this.data = data;
return this.doRequest();
};
ajax.requests.prototype = {
doRequest : function () {
var _this = this;
$.ajax({
data: _this.data
}).done(function(data) {
Handle response and return!
});
}
};
// USAGE
var response = new ajax.requests( yourData );
By returning the $.post, you can use a callback like .done(), chain them together with .then(), etc.
function do_ajax_request(data) {
return $.post( ... ); //RETURN the object
}
var myData = { ... };
do_ajax_request(myData).done(function(result) {
console.log("AJAX complete: " + result);
});
Just another take on this that maybe you hadn't considered. Rather than trying to wrap what is essentially already a wrapper, consider encapsulating your common functionality, like handling errors and dealing with results and using this when executing an ajax request with the existing jQuery ajax wrapper(s)
function handleError(e){
// your common error handling
}
function handleResult(result){
// your common result handling
}
// then every time you execute a request, use your shared functionality
$.post(url, data)
.fail(handleError)
.done(handleResult);
Using code below, you'd need to import config object or declare on top of the functions.
I made two versions for POST and GET respectively
function getJSON(param, absoluteRestUrl = '') {
if (!absoluteRestUrl) {
absoluteRestUrl = config.adminRestEndpoint; // defaultUrl
}
return new Promise(async (resolve, reject) => {
let res = null;
res = await $.getJSON(absoluteRestUrl, param);
resolve(JSON.parse(JSON.stringify(res)));
});
}
function postJSON(param, absoluteRestUrl = '') {
if (!absoluteRestUrl) {
absoluteRestUrl = config.adminRestEndpoint; // defaultUrl
}
return new Promise(async (resolve, reject) => {
let res = null;
res = await $.post(absoluteRestUrl, param, null, 'json');
resolve(JSON.parse(JSON.stringify(res)));
});
}

How to submit a form and pass some extra parameters to a $.getJSON callback method?

I know how to pass some parameters to a JQuery $.getJSON callback method, thanks to this question:
$.getJSON('/website/json',
{
action: "read",
record: "1"
},
function(data) {
// do something
});
And I can also submit a form to a $.getJSON callback method:
$.getJSON('/website/json', $(formName)
function(data) {
// do something
});
But I want to pass some parameters AND submit some form elements. How can I combine the two things togheter?
I could serialize the form elements and manually add some parameters to the url, and it looks like it works:
$.getJSON('/website/json',
'action=read&record=1&'
+ $(formName).serialize(),
function(data) {
// do something
});
But it doesn't look very elegant. Is this the proper way, or there's a better way to do it?
We could implement the functionality demonstrated in this answer as a custom jQuery instance method which produces an object of key/value pairs from a form and combines it with the properties that aren't derived from the form:
$.fn.formObject = function (obj) {
obj = obj || {};
$.each(this.serializeArray(), function (_, kv) {
obj[kv.name] = kv.value;
});
return obj;
};
$.getJSON('/website/json', $(formName).formObject({
action: "read",
record: "1"
}), function(data) {
// do something
});
Make an Ajax post to send the data to the server. Retrieve the parameter data in the backend code along with the form data.
var formData = {data from form};
formData.action = 'read';
formData.post = '1';
$.ajax({
url: '/website/json',
type: "post",
data: formData
}).done(function (data) {
// remove prior values set upon request response
formData.action = null;
formData.post = null;
});

Using Backbone Fetch Success Callback to Change Data Before Initializing View

I'm looking for a way to intercept the value returned from a server when I fetch a backbone model (a collection, strictly speaking) from the server, then modify it before continuing. I would think that I could do something like this
SessionController.prototype._initPages = function() {
return App.pages.fetch({
reset: true,
success: function(model, response, options) {
//modify the contents of response
}
};
And my modifications would be reflected in the model that's used to initialize the view.
However I was looking at the backbone source and I think I may have misunderstood something.
fetch: function(options) {
options = options ? _.clone(options) : {};
if (options.parse === void 0) options.parse = true;
var success = options.success;
var collection = this;
options.success = function(resp) {
var method = options.reset ? 'reset' : 'set';
collection[method](resp, options); //this line updates the model
if (success) success(collection, resp, options); // my success callback
collection.trigger('sync', collection, resp, options);
};
wrapError(this, options);
return this.sync('read', this, options);
}
For my needs, it seems the two commented lines need to be switched, though I assume I'm just misunderstanding how to use this feature.
How can I modify the server response before it becomes my model?
I think you could just override the parse function to modify your data as needed
http://backbonejs.org/#Model-parse

Javascript Keeping variables in scope on success callback (jquery/backbonejs/parse function)

Below I am using backbone js to fetch a collection. On the request's response, I would like to perform some logic on the collection to massage the data. I am modifying the parse method on the parent collection (source types) to attach a child collection (source accounts) and only include a source type if there are actually source accounts.
I don't want to render this without having all the data loaded primarily, so I figure with javascript the only way to be safe is with a success callback.
As you can see in the below code, inside the parse function, I construct a new object called "response_object". The issue is that when i attempt to pack this object inside the success callback, the collection does not include any of the object that i packed into it. How would you rewrite this to make this work correctly?
window.AdminSourceTypes = Backbone.Collection.extend({
model: window.AdminSourceType,
url: '/api/sources',
parse: function(response){
// create response object
response_object = [];
x = 0;
_.each(response, function(item){
//get child collection (accounts) from one of "source type's" attributes
collection = new window.AdminAccounts();
collection.url = item.accounts_url;
//get all accounts
collection.fetch({
//only add the source type to the response object
//if there are accounts associated to it
success: function(accounts_collection){
if(accounts_collection.size() > 0){
response_object[x] = item;
}
}
});
x++;
});
return response_object;
}
});
This is what I went with:
window.sources = new window.AdminSourceTypes({
events: {
'reload':'render'
}
render: function(){... bla bla .... }
});
window.sources.fetch({});
window.AdminSourceTypes = Backbone.Collection.extend({
model: window.AdminSourceType,
url: '/api/sources',
parse: function(response){
cmp = this;
response_object = [];
x = 0;
y = 0;
_.each(response, function(item){‣
collection = new window.AdminAccounts();
collection.url = item.accounts_url;
collection.fetch({
success: function(data){
x++;
if(data.size()>0){
item.accounts = collection;
window.sources.add(item);
window.sources.trigger('reload');
}
}
});
});
}
});
So instead of waiting for the success callback, i'm just going to have the parse method return nothing, and just have the item get added to the collection if it satisifes my condition.

Reusing 'data' passed in the jquery-ajax call

I'm using jquery's .ajax() method on a button click.
I wanted to know if there a way in whcih I can use the data that I passed in the data-part of the AJAX call in my success() function.
This is my code,
$.ajax({
url: //my URL here..
type: 'POST',
data:{
projDets : projDetailsArray,
},
datatype:'html',
error: function(){
alert('Error loading Project Information');
},
success: function(html){
//I wanted to re-use 'projDets' that I'm passing in the
//'data' part of my code..
}
});
Any help will be appreciated.
Thanks
You could wrap the $.ajax parameter in a closure, set up the "data" value as a local variable, and then reference it both for the "data" value and inside the "success" function:
$.ajax(function() {
var data = {
projDets: projDetailArray
// ...
};
return {
url: // your URL here..
type: 'POST',
data: data,
datatype:'html',
error: function(){
alert('Error loading Project Information');
},
success: function(html){
// just reference "data" here!
}
};
}());
Pritish - a quick and dirty way would be to store the json array in a jquery .data() object and then retrieve it as required.
1st, set the data: element to a named array:
// set 'outside' of the $ajax call
var projDetailsData = {projDets : projDetailsArray};
// now store it in a div data object
$("#targetDiv").data("myparams", projDetailsData);
// the data part of the $ajax call
data: projDetailsData,
to retrieve it again:
// get the value stored and call the $ajax method again with it
var projDetailsDataCopy = $("#targetDiv").data("myparams");
worth a try maybe!!
jim
[edit] - also, you could of course store the array in a module level vaiable -yuk!! :)

Categories

Resources