Backbone .fetch() clean data rewriting - javascript

I'd like to make a clean request with backbone on a fetch call. My API's url is /users/, and I want to pass data :
var users = new UsersCollection({ users_id: "1|2|3" });
users.fetch({
data: "users_id=1|2|3"
});
Users is a collection of UserModel.
But the url becomes /users/?users_id=1|2|3 but I want it to be /users/1|2|3.
I've a .htaccess with the following line RewriteRule ^(.*)/$ /api.php?fct=$1 [L]
How can I do it ?

I think that using query params for specifying which models the REST api should ask for is better than the "1|2|3" syntax, but if the specifications is to generate a /users/1|2|3 url it can be achieved like this:
var UsersCollection = Backbone.Collection.extend({
initialize: function(models, options){
this.requestedModelsId = options.modelsId;
},
url: function(){
return "/users/" + this.requestedModelsId.join("|"); //generates /users/1|2|3 if for requestedModelsId [1,2,3]
}
});
var users = new UsersCollection(undefined, {modelsId : [1,2,3]});
users.fetch();
This way the responsibility is left for the collection to know what to fetch for and how to fetch it.

Related

Add data to JQuery Form

First of I admit that I am really bad at js and just got started. I have this snippet in the repository:
function sendReport() {
$.post($('#reportForm').attr('action') + '/post', $("#reportForm").serialize()).done(function() {
reportManager.run();
});
}
And I want to add data to it. I want the webservice that is receiving the post to receive an additional key/value-pair. I tried something like
var data = $('#reportForm').serializeArray();
data.push({name: 'stuff', value: 'blaha'});
$.post(data, $("#reportForm").serialize()).done(function() {
reportManager.run();
});
Didn't work at all and I would really appreciate any help with this.
EDIT:
Tried doing the suggestion below, didn't work. Tried this just to verify that the new parameter didn't ruin anything:
//data to post
var data = $('#reportForm').serializeArray();
//url to post
var url = $('#reportForm').attr('action') + '/post';
//options required for jQuery.post
var options = { "data":data, "url": url };
$.post(options).done(function() {
reportManager.run();
});
That doesn't work. I'm getting an error like this on the server:
noHandlerFound No mapping found for HTTP request with URI [/[object Object]]
I am considering that something else in the code might be using some implicit behaviour, but I find it strange that trying the code above(without even adding new data) can break the current working behaviour.
You are not providing uri parameter for post method, you should use something similar to:
//data to post
var data = $('#reportForm').serializeArray();
data.push({name: 'stuff', value: 'blaha'});
//url to post
var url = $('#reportForm').attr('action') + '/post';
//options required for jQuery.post
var options = { "data":data, "url": url };
$.post(options).done(function() {
reportManager.run();
});

youtube api: get view count of videos in a 'search list' request

I am using the Youtube Javascript API to retrieve a set of videos matching a search string.
It's working great, but I can't seem to find a way to get the statistics (esp. view count) of each video returned in the results.
I didn't find any mention of result statistics in the API documentation.
Is this possible, or do I have to do an individual query for each returned id?
CODE
function init() {
gapi.client.setApiKey(API_KEY);
gapi.client.load('youtube', 'v3');
}
function search() {
var q = $('#query').val();
var request = gapi.client.youtube.search.list({
q: q,
part: 'snippet',
type: 'video'
});
request.execute(function(response) {
var str = JSON.stringify(response.result);
$('#search-container').html('<pre>' + str + '</pre>');
});
}
do I have to do an individual query for each returned id?
No ! You only need to make only one another request with the result of your previous request.
1 - Actually you have this :
var request = gapi.client.youtube.search.list({
q: q,
part: 'snippet',
type: 'video'
});
request.execute(function(response) {
var str = JSON.stringify(response.result);
$('#search-container').html('<pre>' + str + '</pre>');
});
This request give you the id of some YouTube video.
2 - Then you need to concatenate all this video's ID separated with a comma.
Example : 'P95nErnCoC4, 1d6z0gyA5ys' See this post: Create comma-delimited string
3 - You need to create another request with the ressource videos.list
var request = gapi.client.youtube.search.list({
part: 'statistics',
id: 'P95nErnCoC4, 1d6z0gyA5ys, id_next.....' //concatenate ID
});
request.execute(function(response) {
console.log(response);
});
Then you have statistics in only one more request.
The above poster has the right concept but is issuing the wrong request the "part: 'statistics'" is not accessible through "gapi.client.youtube.search.list" request.
in order to access the statistics parameter you need to use the "gapi.client.youtube.videos.list" request which can provide all the meta data.
this request has access to the analytics api which i think is bundled with the v3 client api. great working example is as follows:
https://developers.google.com/youtube/analytics/v1/code_samples/javascript

how to create a resource factory with dynamic URL for the resource

I am using angular in a mobile app. I want to use angular's $resource to create resources to get data from my restful server. Also i am using multiple-domain support. Each domain has its own URL which is the base URL for all server queries. To dynamically provide base URL i created a service called domainService. I can get the base URL like :
var baseURL = domainService.getBaseURL()
The problem is when i m creating the resource this method can't be used to change the base URL dynamically. As factory is singleton only one instance is created.
angular.module('resources.announcementResource',[])
.factory('announcementResource',function(domainService,$resource) {
var baseURL = domainService.getBaseURL() + '/announcement/:id';
return new $resource(baseURL , {
id:'#id'
});
});
In this case the url doesn't changes. I have also tried the solution from:
How to create a dynamic file resource from angular service factory? like this
angular.module('resources.announcementResource',[])
.factory('announcementResource',function(domainService,$resource) {
var announcementResource = {};
announcementResource.getResource = function() {
var baseURL = domainService.getBaseURL() + '/announcement/:id';
return $resource(baseURL , {
id:'#id'
});
}
return announcementResource;
});
but the problem in this was i am using same resource to create new announcements as well. So i can't get the new resource object and can't call $save on this like this
var announcement = announcementResource.getResource().$save();
I have also tried some other solution like :
angular.module('resources.announcementResource',[])
.factory('announcementResource',function(domainService,$resource) {
return new $resource(getBaseURL() , {
id:'#id'
});
function getBaseURL() {
return domainService.getBaseURL() + '/announcement/:id';
}
//return announcementResource;
});
Is there a way to do this?

Backbone Collection Fetch and the form of the Request

I have a backbone collection
var Stuff = Backbone.Collection.extend({
url: "stuff/"
model: StuffModel
});
I also have an array of ids:
var ids = [ 1, 2, 3, 4 ];
As per the docs, I call fetch on Stuff like so:
this.collection.fetch( { $.param({ ids : exercise_ids.join( "," )})});
This sends a request to the server of the form:
/stuff/?ids=1,2,3,4
This works, but I'm not happy with the form of the request. Is there a way I can send the request with the following form (ie not use the querystring)
/stuff/1,2,3,4
Thanks (in advance) for your help.
Assuming the backend sees [param] as ids when you do /stuff/[param] then there is no difference in functionality. These request are made behind the scenes and don't affect the browser's address bar so there isn't really any concern here. If you want to format your url you can define url as a function in your Backbone Collection
var Stuff = Backbone.Collection.extend({
initialize: function(models, options) {
this.ids = options.ids
//bind functions to 'this' so that you can access ids
_.bind(this, 'setIds', 'url');
},
setIds: function(ids) {
this.ids = ids;
//return 'this' to allow chaining
return this;
},
url: function() {
return 'stuff/' + this.ids.join(',')
}
});
myCollection.setIds([1,2,3,4]).fetch()

How do I fetch a single model in Backbone?

I have a Clock model in Backbone:
var Clock = Backbone.Model.extend({});
I'm trying to get an instance of that that has the latest information from /clocks/123. Some things I've tried:
a "class"-level method
Clock.fetch(123)
// TypeError: Object function (){ ... } has no method 'fetch'
creating an instance and then calling fetch on it:
c = new Clock({id: 123})
c.fetch()
// Error: A 'url' property or function must be specified
a collection
I tried creating an AllClocks collection resource (even though I have no use for such a thing on the page):
var AllClocks = Backbone.Collection.extend({
model: Clock,
url: '/clocks/'
});
var allClocks = new AllClocks();
allClocks.fetch(123);
// returns everything from /clocks/
How do I just get one API-backed Clock?
Try specifying urlRoot in the model:
From the docs:
var Book = Backbone.Model.extend({urlRoot : '/books'});
var solaris = new Book({id: "1083-lem-solaris"});
solaris.fetch();
Your second approach is the approach I have used. Try adding the following to your Clock model:
url : function() {
var base = 'clocks';
if (this.isNew()) return base;
return base + (base.charAt(base.length - 1) == '/' ? '' : '/') + this.id;
},
This approach assumes that you have implemented controllers with the hashbang in your URL like so, http://www.mydomain.com/#clocks/123 , but it should work even if you haven't yet.
I personally recommend, following the Model#url method documentation
model = new Model(id: 1)
view = new View(model: model)
collection = new Collection([model])
model.fetch()
in your collection remember to add the collection url:
url: "/models"
and in your View's initialize function do:
this.model.bind("change", this.render)
this way backbone will do an ajax request using this url:
"/models/1"
your model will be updated and the view rendered, without modifying Collection#url or Model#urlRoot
note:
sorry this example came out in coffee script, but you can easily translate it to js adding var statements
var Person = Backbone.Model.extend({urlRoot : '/person/details'});
var myName = new Person({id: "12345"});
myName.fetch();
As a result you make a Ajax request on the
URL http://[domainName]/person/details/id
and you have the JSON response back.
Enjoiiii !!!
...and do this if you don't want the trailing slash on the model urlRoot:
url : function() {
return this.urlRoot + this.id;
},
You probably should be accessing the object trough a collection and keeping it in the collection all the time. This is how to do it:
var AllClocks = Backbone.Collection.extend({
model: Clock,
url: '/clocks/'
});
var allClocks = new AllClocks();
my_clock = allClocks.add({id: 123});
my_clock.fetch()
I want to use RESTful url,but I couldn't understand why 'postId' can't be added to base url.
var PostModel = Backbone.Model.extend({
urlRoot: 'getBlogPost',
defaults: {
postTitle: "defaultTitle",
postTime: "1970-01-01",
postContent: "defaultContent",
postAuthor: "anonymous"
}
});
var post = new PostModel({
postId: 1
});
alert(post.url());
Then I know only after I set 'idAttribute' as 'postId' in Model can I get the right url.
like this:
var PostModel = Backbone.Model.extend({
idAttribute: 'postId',
urlRoot: 'getBlogPost',
defaults: {
postTitle: "defaultTitle",
postTime: "1970-01-01",
postContent: "defaultContent",
postAuthor: "anonymous"
}
});

Categories

Resources