Fetching models from the server - backbone.js

I have a RESTful service which have being written using Node.js. If I open http://localhost:5000/links in the browser I will get the collection of links:
[{"_id":"5597f5d3e9a768531c07468a","uri":"http://google.com","title":"google","__v":0,"tags":["one","two"]}]
I need to get this collection from backbone application:
(function () {
var Link = Backbone.Model.extend({});
var LinkCollection = Backbone.Collection.extend({
model: Link,
url: 'http://localhost:5000/links'
});
var links = new LinkCollection();
links.fetch();
console.log(links);
console.log(links.length);
})();
Here is a console:
I can see my object the right side of the console (c3.attributes). But why the length of collection is zero? And how can I get this object?

Classic backbone issue.
Try this:
links.fetch({
success:function(response) {
//here are your results
}
});
Edit: Also I think a collection return a promise so an alternative solution could be:
links.fetch().then(function(response) {
});
haven't use it myself but I think it should work. Hope it helps.

Related

Backbone.js / require.js - Override model function to work with backend as a service

Good morning guys. I have a little understanding problem with backbone.js. i have a javascript sdk from a backend as a service with some getter and setter methods to get datas from this platform.
I have load this javascript sdk with require.js an it´s work fine. Now i need to create some models that work with this getter and setter methods to get this data to my collection an finally to my view. I do not have any clue...maybe someone have the right idea for me.
This is my current model:
define(['jquery','underscore','backbone'], function($,_,Backbone) {
var holidayPerson = Backbone.Model.extend({
initialize: function() {
console.log("init model holidayPerson");
this.on("change", function(data) {
console.log("change model holidayPerson"+JSON.stringify(data));
});
}
});
return holidayPerson;
});
Actually i create an instance of my model in my view:
define(['jquery','underscore','backbone','text!tpl/dashboard.html','holidayPerson','apio'], function($,_,Backbone,tpl, holidayperson, apio) {
template = _.template(tpl);
var usermodel = new holidayperson();
var dashboardView = Backbone.View.extend({
id: 'givenname',
initialize: function() {
console.log("dashboard view load");
usermodel.on('change', this.render);
var user = new apio.User();
user.setUserName('xxx');
user.setPassword('xxx');
apio.Datastore.configureWithCredentials(user);
apio.employee.getemployees("firstName like \"jon\" and lastName like \"doe\"", {
onOk: function (objects) {
console.log("apio: " + JSON.stringify(objects));
usermodel.set({mail: objects[0]['data']['mail'],lastname: objects[0]['data']['lastName'], username: objects[0]['data']['userName'], superior: objects[0]['data']['superior']});
}
});
},
render: function() {
console.log("render dashboard view");
console.log(usermodel.get('mail'));
console.log(usermodel.get('lastname'));
this.$el.html(template());
return this;
}
});
return dashboardView;
});
I think this not the right way...can i override the getter and setter method from this model ? Or maybe the url function ? Anyone now what is the best practice ?
Thanks a lot :-)
First of all, make sure that your render operation is asynchronous, as your API call will be and the usermodel params won't be set until that operation completes. If you render method fires before that, it will render the empty usermodel, since the data will not be there yet.
Second, a model need not fetch its own data, in my opinion. If you are going to have multiple users, you could use a collection to hold those users and then override the collection's sync method to handle the fetching of data from the API, but if there's no collection, it seems logical to me to have a method that does the data fetching and setting thereafter, as you've done.

backbone.js - how can i fetch local or server data

I am very new to backbone.js, to try it out I made a function to append an element using my array. But I don't know how to fetch the same from server or my local path.
I tried with some tutorial but still I couldn't get any good result. Can any one correct my function to fetch the data from local folder or server?
code :
this is my local path: '..data/data.json'
(function($){
var student = [
{name:'student1'},
{name:'student2'},
{name:'student3'}
]
var model = Backbone.Model.extend({
defaults:{
name:'default name'
}
});
var collection = Backbone.Collection.extend({
model:model
});
var itemViews = Backbone.View.extend({
tagname:'li',
render:function(){
this.$el.html(this.model.get('name'));
return this;
}
})
var view = Backbone.View.extend({
el: $("#contacts"),
initialize:function(){
this.collection = new collection(student);
this.render();
},
render:function(){
var that = this;
_.each(this.collection.models, function(item){
that.renderName(item);
})
},
renderName:function(item){
var itemView = new itemViews({model:item});
this.$el.append(itemView.render().el);
}
});
Collections have the url property which links to the url where the models can be fetched (in a proper JSON format of course).
If you have a RESTful API you can tie them directly to a collection on your backend.
In your case you can modify the collection definition as follows
var collection = Backbone.Collection.extend({
model:model,
url: '..data/data.json' //OR WHATEVER THE URL IS
});
Then when instantiating your collection you have to call the fetch() method to fill in the collection.
myCollection = new collection();
myCollection.fetch();
For more information see this post
Backbone will call GET, POST, DELETE, etc on that same url depending on what needs to be sent or received from the server. So if you are building the REST api, your controller or router should route the appropriate functions to those methods. See below for exact mapping:
create → POST /collection
read → GET /collection[/id]
update → PUT /collection/id
delete → DELETE /collection/id
As a side note, if you have no control over the JOSN that is returned from the server, you can format it in any format you like in the parse function.
parse: function(response) { return response.itemYouWantAdded; }
This would be the case if your server is returning an object within an object, such as twitter feeds.
Or you could simply populate the model from the response manually in the parse function
parse: function(response) { var tmpModel = {
item1:response.item1,
item2:response.item2
};
return tmpModel; }
Hope this helps.
You can set a URL for your model or for your collection. Then when you run fetch it will read your JSON straight into either a single model or a collection of models. So in your case, your collection might look like
var collection = Backbone.Collection.extend({
url: '..data/data.json',
model: model
});
collection.fetch(); // Could also use collection.reset()
You just need to make sure your JSON is formatted properly to match your model's attributes.

How can I create custom GET urls with params using Backbone?

I've noticed that some web sites offer Ajax-ian search that refreshes the URL and displays the GET params used, for example:
someapp.com/search/Tokyo?price_min=80&price_max=300
As a result of an Ajax GET request.
I want to know how can I accomplish this by using Backbone.js, I understand that by using backbone's push state this may be possible, am I right?
How could I define a route like that (let's say the same case, scoped to /search) for a Place model for example?
Where would I do this? in a Router or in a Model?
I appreciate all the answers regarding this topic. And I apologize in advance for not providing any code, I usually do, but this exercise will be a proof of concept I'd like to make, and I hope backbone is the right tool for the job.
Thank you!
This is a working example of the solution - jsfiddle.net/avrelian/dGr8Y/, except that jsFiddle does not allow Backbone.history.navigate method to function properly.
Suppose, we have a button
<input class="fetch-button" type="button" value="Fetch" />​
and a handler
$('.fetch-button').click(function() {
Backbone.history.navigate('posts/?author=martin', true);
});
This is our collection of posts
var Posts = Backbone.Collection.extend({
url: 'api/posts'
});
This is our Router with a custom parameter extractor
var Router = Backbone.Router.extend({
routes: {
'posts/?:filters': 'filterPosts'
},
filterPosts: function(filters){
posts.fetch({data: $.param(filters)});
},
_extractParameters: function(route, fragment) {
var result = route.exec(fragment).slice(1);
result.unshift(deparam(result[result.length-1]));
return result.slice(0,-1);
}
});
It is simplified $.deparam analog. You could use your own instead.
var deparam = function(paramString){
var result = {};
if( ! paramString){
return result;
}
$.each(paramString.split('&'), function(index, value){
if(value){
var param = value.split('=');
result[param[0]] = param[1];
}
});
return result;
};
And finally, instantiation of posts collection and router object
var posts = new Posts;
var router = new Router;
Backbone.history.start();
When a user clicks on the button address bar changes to myapp.com/s/#posts?author=martin. Please, note the sign #. We use a hash query string. Of course, you can use push state, but it is not widespread yet.

using underscore variables with Backbone Boilerplate fetchTemplate function

I am building an application using the Backbone Boilerplate, and am having some trouble getting underscore template variables to work. I have a resource named Goal. My Goal View's render function looks like this:
render: function(done) {
var view = this;
namespace.fetchTemplate(this.template, function(tmpl) {
view.el.innerHTML = tmpl();
done(view.el);
});
}
I'm calling it inside of another view, like so:
var Goal = namespace.module("goal");
App.View = Backbone.View.extend({
addGoal: function(done) {
var view = new Goal.Views.GoalList({model: Goal.Model});
view.render(function(el) {
$('#goal-list').append(el);
});
}
});
I'm using local storage to save my data, and it's being added just fine. I can see it in the browser, but for some reason, when I load up the app, and try to fetch existing data, i get this error:
ReferenceError: Can't find variable: title
Where title is the only key I'm storing. It is a direct result of calling:
tmpl();
Any thoughts are greatly appreciated.
Your template is looking for a variable title, probably like this <%- title %>. You need to pass it an object like this tmpl({ title: 'Some title' })
Turns out, I wasn't passing in the model when i created the view, which was making it impossible to get the models data. Once I passed in the model correctly, I could then pass the data to tmpl, as correctly stated by #abraham.
render: function(done) {
var
view = this,
data = this.model.toJSON();
clam.fetchTemplate(this.template, function(tmpl) {
view.el.innerHTML = tmpl(data);
done(view.el);
});
},

Backbone.js - fetch data and display

I'm just beginning out on Backbone.js. Here's my code.
$(function(){
//Backbone Model
var Cat = Backbone.Model.extend({});
// create a collection
var CatCollection = Backbone.Collection.extend({
model: Cat,
url: 'http://localhost/cats/index.php/cats/index'
});
var catCollection = new CatCollection();
catCollection.fetch();
// Backbone view
var CatView = Backbone.View.extend({
el: $("#contents"),
initialize: function() {
this.render();
},
render: function() {
this.el.html(catCollection);
}
});
var catView = new CatView();
});
What I am doing is.
Create a backbone model
Create a collection using the model I created.
Fetch data from MySQL database - this returns a JSON data object.
Display the fetched data in the div "#contents".
On google Chrome, I can see that the "fetch()" method works, because I can see my JSON object returned as
[{"id":"1","name":"stella","age":"5"},{"id":"2","name":"Max","age":"2"}]
But if I do "alert(catCollection)" after the fetch, it displays "[object] [object]".
What is the best way of displaying this?
You should use the templates in JST array.
$(this.el).html($(JST["comments/item"](model.toJSON())));
"comments\item" is the template path and name
If you are using Rails, just use the Jammit and write templates with ERB (default) or Jade
The backbone.js documentation give an example like so:
alert(JSON.stringify(catCollection));
http://backbonejs.org/#Collection-toJSON
Use console.log.

Resources