Setting Default Options for Backbone Collections - backbone.js

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

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 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: ''
}

Backbone.js: Dynamic model/collection url based on user input

I'm total new to Backbone so please pointing me the right way to do it. Here is what I have:
A Backbone login View with 3 inputs: serverIP, username, password. I am doing all the validation and send jquery ajax() request to my backend host based on the serverIP that the user has to enter earlier.
My backend is js PHP using Slim restful framework, check user, password like usual basic stuff.
On the callback of successful ajax() call, I want to set the urlRoot for latter use of all models and collections as I'm using Slim for all database interactions and this PHP file located on the server.
I tried to set it on the global app variable like this in app.js:
var app = {
api_url: '',
views: {},
models: {},
routers: {},
utils: {},
adapters: {}
};
In the callback of login view I set:
app.api_url = "http://"+serverIP;
And try to use app.api_url in backbone model url but it's apparently undefined.
May be this is not the correct approach I'm trying and I messed up with the variable scope? Then how can I set model.url from the view? Please, any suggestions are much appreciated.
Thanks,
Hungnd
EDIT: Ok, I will try to elaborate my problem again:
Here is the login function in my LoginView.js, basically it take user inputs and send to my model to interact with the server, if success navigate to home view:
var user = new app.models.Login();
var userDetails = {
serverIP: $('#serverIP').val(),
username: $('#username').val(),
password: $('#password').val()
};
user.save(userDetails, {
success: function(data) {
/* update the view now */
if(data.error) { // If there is an error, show the error messages
}
else { // If not, send them back to the home page
app.router = new app.routers.AppRouter();
app.router.navigate('home',true);
}
},
error: function() {
/* handle the error code here */
}
Here is my LoginModel.js, get the serverIP from user input on login form and send to the server to process
app.models.Login = Backbone.Model.extend({
urlRoot: function(){
var serverIP = this.get('serverIP');
return "http://"+serverIP+"/api/login";
},
defaults: {
'serverIP': '',
'username': '',
'password': '',
}
});
Now, after successful login, navigate to HomeView.js, on initialize it calls to EmployeeCollection, so far so good
initialize: function () {
//Search result
this.searchResults = new app.models.EmployeeCollection();
this.searchResults.fetch({data: {name: ''}});
this.searchresultsView = new app.views.EmployeeListView({model: this.searchResults});
}
Here is my EmployeeModel.js where I have the problem, I dont know how to access the serverIP variable.
app.models.Employee = Backbone.Model.extend({
urlRoot:"api/employees",
//urlRoot: app.api_url+"/api/employees",
initialize:function () {
this.reports = new app.models.EmployeeCollection();
this.reports.url = app.api_url+'/api/employees/' + this.id + '/reports';
}
});
app.models.EmployeeCollection = Backbone.Collection.extend({
model: app.models.Employee,
//url: "api/employees",
url: function() {
//How to get serverIP?
},
});
All models in backbone already have an url property which will be used to fetch data. In your case you could define it as a function to generate url dynamically.
Here is an example :
//we are inside the definition of the loginModel
data: {
serverIP : null,
username : null,
password : null
},
url: function() {
var url = "rootUrl",
data = this.get("data");
return function() {
return url + '?' + $.param(data);
};
}
url is then defined as a closure, and object being references in javascript, the url generated will use the current values in the data object.

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

How to specify url and header in backbone to use crud method on my model?

i need to make request on server that needs of particulary api key and i need to use the crud method tu update my model and as soon as...
For example i have this code in ajax to get element from server:
function getapi() {
$.ajax({
url: 'https://api.parse.com/1/classes/autolavaggi/QSfl*****',
type: 'GET',
dataType: 'json',
success: function(obj) {
alert("nome autolavaggio "+obj.nome);
},
error: function() {
alert('Errore');
},
beforeSend: setHeader
});
}
//GET GET GET GET GET GET GET GET Header Header Header Header
function setHeader(xhr) {
xhr.setRequestHeader('X-Parse-Application-Id', 'aqLJlmE2rRXBOy***************');
xhr.setRequestHeader('X-Parse-REST-API-Key', 'gvT2Isd5vAvjgq*****************');
}
How can i do to assign this particular ajax call to crud method save,fetch or another??
Each of the crud methods accept an options hash that will get forwarded to the ajax call. In the case of a collection fetch:
var Model = Backbone.Model.extend({});
var Collection = Backbone.Collection.extend({
model: Model,
url: 'https://api.parse.com/1/classes/autolavaggi/QSfl*****'
});
var setHeader = function (xhr) {
xhr.setRequestHeader('X-Parse-Application-Id', 'aqLJlmE2rRXBOy***************');
xhr.setRequestHeader('X-Parse-REST-API-Key', 'gvT2Isd5vAvjgq*****************');
}
var collection = new Collection();
collection.fetch({ beforeSend: setHeader });
Alternatively, override sync:
var sync = Backbone.sync;
Backbone.sync = function(method, model, options) {
options.beforeSend = function (xhr) {
xhr.setRequestHeader('X-Parse-Application-Id', 'aqLJlmE2rRXBOy***************');
xhr.setRequestHeader('X-Parse-REST-API-Key', 'gvT2Isd5vAvjgq*****************');
};
// Update other options here.
sync(method, model, options);
};

Resources