How do I fetch a single model in Backbone? - javascript

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

Related

Backbone API fetch() from Model using API authentication

I have problem with my Backbone mobile app (using Cordova, Require, Handlebars, etc..).
In particular the console log of chrome give me this result:
.
I've tried different solutions taken by debugging and searching on the web.
The first are defining the urlRoot in my Model.backbone and calling the function mymodel.fetch(). And the result given is: .
This is the code:
var MyModel = Backbone.Model.extend({
constructorName: "MyModel",
urlRoot: 'http://192.168.56.101/XXX/api/categories/26?io_format=JSON'
});
myView: function() {
var model = new MyModel();
model.fetch();
// create the view
var page = new MyView({
model: model
});
// show the view
this.changePage(page);
},
The second solution is embedding the API KEY in the urlRoot. Like that:
var MyModel = Backbone.Model.extend({
constructorName: "MyModel",
urlRoot: 'http://IYI6M35MLB8UVW38fhj9RY3YPQWRX5X8H#192.168.56.101/XXX/api/categories/26?io_format=JSON'
});
The last solution that we tried was passing the header in the fetch call. Like this code:
myView: function() {
var model = new MyModel();
model.fetch({
headers: {
'Authorization': 'Basic IYI6M35MLB8UVW38Y99RrgsrPQWRX5X8H:'
}
});
// create the view
var page = new MyView({
model: model
});
// show the view
this.changePage(page);
},
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
All of this solutions give me the same result, like "Chrome Console LOG", he sad me "Unauthorized etc.." like the image.
Can you give me some help? How can I bring JSON object in a model in Backbone using API with authentication by Username?

Proper way of populating Backbone Collection

I have the following Backbone Model and Collection
/**
* DataPoint
*/
var DataPoint = Backbone.Model.extend({
defaults: {
ts: null,
value: null
}
});
var DataPointCollection = Backbone.Collection.extend({
model: DataPoint
});
In order to populate and do what I need to do with the data I do something similar to this:
url = '/api/v1/database/1/data';
$.getJSON(url, params, function(data) {
var dps = new DataPointCollection;
dps.add(data.datapoints);
//Now do stuff with dps
});
I'm sure there is a better way to do this with Backbone but not sure how. I feel it should be more like telling the DataPoint collection to populate itself.
How to approach this on backbone?
Have a look at the docs, fetch is what you're looking for; here's the example took from there:
var accounts = new Backbone.Collection;
accounts.url = '/accounts';
accounts.fetch();

JavaScript: unable to access object properties

I'm having trouble accessing the properties of a simple object.
This is what I get when I run alert(JSON.stringify(user)):
{"username": "david", "biography": "Hello world."}
But this is what I get when I run alert(user.username):
undefined
I've also tried user["username"] with the same result. This is in the context of a Backbone application using Handlebars. Here is the Backbone part:
var User = Backbone.Model.extend({
urlRoot: 'http://api.example.com/user',
});
var Router = Backbone.Router.extend({
routes: {
":username": "profile"
},
profile: function (username) {
var user = new User({id: username});
user.fetch({
beforeSend: authenticate,
success: function() {
var profile = new Profile({user: user});
profile.render();
}
});
}
});
var Profile = Backbone.View.extend({
render: function() {
var source = $("#profile").html();
var template = Handlebars.compile(source);
user = this.options.user;
var html = template(user);
$("#content section").html(html);
}
});
What might be the cause such an issue?
if you user object is a backbone model, then try this
console.log(user.get('username'));
or
cosole.log(user.attributes.username);
This is working for me
var user = {"username": "david", "biography": "Hello world."};
alert (user.username);
alert (user["username"]);
JSON.stringify will look for a toJSON function and use the return value of that as the JSON it uses.
Backbone probably does some fancy coding to make it easier to use its model objects. Since they don't think you want all the junk they put in, they provided a clean toJSON() result for you.
#Rayweb_on has the rest of the answer.

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

Setting asp.net MVC4 web api route url in javascript is returning empty string

Here is the code that I am using to set the api url:
var clientUrl = '#Url.RouteUrl("ApiControllerAction", new { httproute="", controller = "Client"})';
In my route.config the route looks like this:
routes.MapHttpRoute(
name: "ApiControllerAction",
routeTemplate: "api/{controller}/{action}/{id}"
);
And the action on my controller that I am trying to hit is this:
[ActionName("clients")]
public IQueryable<Client> GetClients(int id)
{
return Uow.Clients.GetClients(id);
}
I have a function in javascript that is trying to hit this api, but I am getting a 404:
var getClients = function (id) {
return $.ajax(clientUrl + "/clients/" + id)
};
When I call getClients(1) the url is trying to hit is this:
localhost:12345/clients/1
Rather than my expected url of this:
localhost:12345/api/client/clients/1
Any idea where this is going wrong? I had this working in another project and can't remember if there is something else I am supposed to do. If I inspect the javascript the clientUrl = ''.
I came across this answer How to create ASP.NET Web API Url? which helped.
Example code for my answer here on GitHub
You can alter your #Url.RouteUrl code to include both the action name and the "ID" which currently appears not to be optional for your action route... this is probably why it is failing to find a match and returning an empty string. So try:
var clientUrl = '#Url.RouteUrl("ApiControllerAction", new { httproute="", controller = "Client", action = "clients" id=#... })';
NB. id=#... })'; at the end ... being what ever the id is going to be var or property on a model etc...
Or
You could of course just make ID optional which will also work:
config.Routes.MapHttpRoute(
name: "ApiControllerAction",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
Or
You may find it cleaner to avoid using an action... clients could live in its own controller ClientsController and you can use the routes and defaults to route to it:
routes.MapHttpRoute(
name: "ApiControllerAction",
routeTemplate: "api/client/clients/{id}",
defaults: new { controller="Clients" }
);
Then this should give you the required response:
var clientUrl = '#Url.RouteUrl("ApiControllerAction", new { httproute="", controller = "Clients" })';
//api/client/clients/
and...
var clientUrl = '#Url.RouteUrl("ApiControllerAction", new { httproute="", controller = "Clients", id=#... })';
//api/client/clients/x
Try to set the clientUrl like this:
var clientUrl = '#Url.RouteUrl("ApiControllerAction", new { httproute="", controller = "Client", action = "clients"})';
And then in change getClients to this:
var getClients = function (id) {
return $.ajax(clientUrl + "/" + id)
};

Categories

Resources