Wrapping my head around a unique backbone.js collection - backbone.js

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

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

Make the URL for a Backbone Collection Dynamic

I am a BackboneJS newbie.
I have scenario where I want to make the URL of my collection completely dynamic.
Essentially following are the 2 URLs that I want to load my collection from:
http://localhost:3001/employees
http://localhost:3001/employees/searchByName/John
Both the URL return the same collection, the difference being that the first URL returns all the results while the 2nd one is based on a search criteria.
I have a search field in my form and based on whether the search field is empty or contains a search value, I want to toggle between these URLs. All the examples I have seen either do records filter in the view or the only dynamic url I have seen is where an id is added to the existing url to get a single record instead of all records.
So my first question is : How can I achieve this dynamic URL fetching for my collection?
My 2nd question is : How do I call my collection differently based on the search field value so that the collection picks the appropriate value.
someCollection = Backbone.Collection.extend({
url: function() {
if(this.searchName!=null)
return baseURL + "/" + "searchByName" + "/" + this.searchName;
else
return base_URL;
},
search: function(searchTerm)
{
console.log("Search Term =" + searchTerm);
var results = new someCollection();
results.searchName = searchTerm;
results.fetch({
success: function()
{
vent.trigger("search:results", results);
},
error: function(collection, response){}
});
},
parse: function(response, options)
{
return response;
}
});
So far my code for the Collection is this but I don't think I am going the right direction.
Try something like this:
var SomeCollection = Backbone.Collection.extend({
url: function() {
if (this.searchName) {
return this.baseURL + "/" + "searchByName" + "/" + this.searchName;
} else {
return this.baseURL;
}
},
searchName: null,
search: function(searchName) {
console.log("Search Name =" + searchName);
this.searchName = searchName;
this.fetch({
success: function() {
vent.trigger("search:results", results);
},
error: function(collection, response){
console.log("Something went wrong");
}
});
},
parse: function(response, options) {
return response;
}
});
var aFilteredCollection = new SomeCollection();
aFilteredCollection.search("Name goes here");
var aNonFilteredCollection = new SomeCollection();
aNonFilteredCollection.search();

angular js getting data from laravel and print it

Hi I'am trying a simple example of using a controller and a factory to get some data back to the view but for some reason I can't print it.
I managed to get the ajax call to work.
If I type the
$scope.sampleStyles = [{ sample: 'text here', text : 'dasdas'}
and don't use the ajax call it works
UPDATE: if I add an alert before assigning to my scope it works (ajax has time to do his thing)
anyone know how to overcome that?
CODE:
var packageApp = angular.module("packageApp", []);
packageApp.controller("MyController", function($scope, myFactory){
$scope.sampleStyles = [];
function init(){
$scope.sampleStyles = myFactory.getSampleStyles();
}
init();
});
packageApp.factory('myFactory', function($http, $log){
var factory = {};
var sampleStyles = [];
var tempData = {};
factory.update = function(){
$.ajax({
type: 'POST',
url: '/account/fetch-sample-styles',
data: {
source: 'ajax'
},
success: function(data, textStatus, XMLHttpRequest){
tempData = data;
}
});
alert(tempData);
sampleStyles = tempData;
}
factory.getSampleStyles = function(){
factory.update();
return sampleStyles;
};
return factory;
});
Are you using the AngularJs $http service? If so it will return a promise which you then operate on. Here is more on promises from the AngularJs docs.
My guess is, you are using an ajax.get(...) with a success callback defined inside. The problem is probably due to the success callback not belonging to the "AngularJs world."
To fix this, you need to tell AngularJs that its scope has changed. Use the $[Root]scope.$apply() function, and have the scope injected into your service as a dependency.
Something like this inside the factory:
$.ajax({
url: "/api/some/end/:point",
...
success: function(data) {
$scope.$apply(function() {
$scope.sampleStyles = data; // etc
});
}
});
I strongly recommend that you look into the $http service, it makes the above code much nicer, and is designed to play nice with the $scope.
$http.get("/api/end/point").then(function(response) {
// response.data points at the page data sent back, assuming that your
// api endpoint sends back JSON of the likes of
// { status: "SUCCESS", styles: [...] }
$scope.sampleStyles = response.data.styles;
});
EDIT:
Now that you posted some code, it seems like the root of your issue is based on the fact that the ajax get is an async call. Why are you even messing with using a temporary variable? Why not the following?
factory.update = function(){
$.ajax({
type: 'POST',
url: '/account/fetch-sample-styles',
data: {
source: 'ajax'
},
success: function(data, textStatus, XMLHttpRequest){
sampleStyles = data;
}
});
}
If you really wanted to make the $.ajax call blocking, you can set async: false in the $.ajax properties.
EDIT 2:
Fixed some broken links, sorry I am a SO newb :(

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

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