Using Collections in Backbone.js - backbone.js

The following would be the model of a simple backbone application. So consider i want to have more than one url calls, i am told i should be using collections(definition is a collection of models).
Model format :
var Books1 = Backbone.Model.extend({
urlRoot: '/books1'
});
var Books2 = Backbone.Model.extend({
urlRoot: '/books2'
});
Collection format :
var Books = Backbone.Collection.extend({
url: '/books'
});
My question is how can i like combine more than one model in a collection ?
To be more clear :
Consider i have currently 8-10 models in a single view(need to call 8+ server requests from a single view). I am succesfully doing this via models. But from my initial research i came to conclusion that i should be using collection which will be a collection of all the models used. So by passing the collection to view, i will be able to call out different models at different part of view as requried.
And how do i use it in a view?
To be more clear :
for a model now i use this.model.save() or newmodel.save() after declaring the model before the place where i need to have the request done.
Cheers

lots of properties is handled via http://underscorejs.org/#result so you can pass urlRoot as function
var Books = Backbone.Model.extend({
urlRoot: function(){
return condition ? '/books' : '/bum'
}
});
same in collection. But I don't think so, its a good idea to combine 2 or more models in one collection. Just make a new collection for another model, if its possible....
what about view?
you can pass collection to view instance like this:
var SomeView = Backbone.View.extend({
initialize: function(opt){
this.collection = new opt.collection
}
});
var someView = new SomeView({collection: Books})

Related

Backbone Model is a function?

I have the following function, which fails when called:
getAll: function() {
return _todos.toJSON();
}
_todos.toJSON is not a function it tells me.
Printing _todos gives me a function for some reason function child().
Why is that the case?
Here's my Backbone.Model:
var _todos = Backbone.Model.extend();
The getAll() function is sitting in my Collection:
var TodoCollection = Backbone.Collection.extend({
model: _todos,
getAll: ...
});
Edit:
I'm actually connecting Backbone with React, so that might change how I do this.
In addition to getAll I have this:
areAllComplete: function() {
return _.every(this.pluck('complete'), true);
}
An example I've been following seems to put getAll and areAllComplete in the Model and doesn't use Collection at all. I couldn't make sense of it, and since I want this to be restful down the road, I added the Collection and moved getAll and other one inside of it.
Perhaps, this is not what I want.
Edit 2:
According to a warning, the output of getAll is expected to be an Object not an array. I should probably add those function to Model not Collection. Need to think about this more.
I think this turned into another question...
The collection model property is used to specify what model class the collection contains and is used to create the proper models when you pass the raw data to your collection. Additionally based on your code if it did work you would have had a collection with just one model.
Aside from that in order to get the JSON of all the models in your collection you can call it's toJSON method
for example todoCollection.toJSON();
Or if you specifically want it in a getAll function (maybe you want to do something else before returning the data) you can do the following
var TodoCollection = Backbone.Collection.extend({
model: Todo,
getAll: function () {
//do something
return this.toJSON();
}
});
//here we are passing in the data directly, but you might get it with a fetch call
var todoStore = new TodoCollection(models);
var todosJson = todoStore.getAll();
Another thing to note is the backbone naming convention is to use PascalCase for classes and camelCase for instances .
That's because Backbone.Model.extend returns a constructor function. When you pass it to a collection via the model property you're just letting the collection know which kind of models it should hold.
To get the JSON for an entire collection, call toJSON() on the collection instance.
var collection = new TodosCollection();
// add models
collection.toJSON();
If you want JSON for one specific model then get a reference to it via the collection API (at, findWhere, get etc) and call toJSON() on that reference.
var model = collection.at(0);
model.toJSON();

An Array to Backbone Collection

I think this is a simple question. It is based of this question.
Filter and sort backbone collection with array of ids
router.on('route:reportCollection', function(assetid) {
var asset = assets.get(assetid);
var reportpointers = asset.get('reportsid');
var filteredReportCollection = new dilzeemQ.Collections.FilteredReportCollection({
});
ohhyearh = filteredReportCollection.filterById(reportpointers);
var reportCollectionView = new dilzeemQ.Views.ReportCollection({
collection: ohhyearh
});
console.log(ohhyearh);
console.log(reports);
$('#pagecontent').html(reportCollectionView.render().$el);
});
I have gotten it to work as I would like except the passing of the collection : ohhyearh
ohhyearh is something like this [child,child] where as I think it is expecting something along the lines of this {child,child}
At the point where you pass ohhyearh to the view, it should be an instanceof Backbone.Collection. That is what the view is expecting, not an array or an object with a property for each child.
Based on the code in the snippet, I would say that your filterById function is probably doing something unexpected and not returning an actual collection. You can either modify it to return new dilzeemQ.Collections.FilteredReportCollection(models) or you can leave it as is, and create a new collection when you pass it to the view:
collection: new dilzeemQ.Collections.FilteredReportCollection(ohhyearh)
This is assuming that your ohhyearh object is an array with Backbone.Model instances. You can pass an array of models to a collection constructor to get a collection of those models.

BackboneJS - How to limit number of models in collection

How can I set a limit to the number of models to get displayed in collection?
So far I have:
var myCollection = new Collection();
myCollection.url = this.model.url() + '/feed';
myCollection.fetch();
I have tried to add:
myCollection.first(20);
but that didnt work, since the first() only works on arrays?
You can use .parse() method. It called with .fetch() and helps to modify server response.
In your case in may be helpful to slice models array you get from backend.
var myCollection = Backbone.Collection.extend({
parse: function(response) {
return response.slice(0,20);
}
});
On every fetch you will have first 20 models in your collection.

How to update model by id in Backbone.js?

I've tried simple example from backbone tutorial and can't get this working
var Person = Backbone.Model.extend({});
var People = Backbone.Collection.extend({
model: Person,
url: "http://localhost:3002/people"
});
var people = new People();
var person = new Person({
id: 3
});
person.fetch({
success: function () {
person.set({age: 23});
person.save();
}
});
I just want to update existing record with id equals to 3 but got an error A "url" property or function must be specified. I'm sure that I didn't make mistake when typing this example but it works in tutorial and doesn't work for me. Is it because of some version changes?
As the error and comments have indicated, you need to specify the url property for the model or add the person model the people collection.
If you would like to fetch your model using the same url as the people collection. You need to add person to the people collection by doing:
var people = new People(person);
// or
people.add(person);
// The fetch url for a person would look like
// GET http://localhost:3002/people/3 Assuming the id of the person is 3.
If you need to use a different url than your collection has specifed the person model. You can specify the url or urlRoot attribute in your Person model.
var Person = Backbone.Model.extend({
urlRoot:'http://localhost:3002/person'
});
// The fetch url for a person would look like
// GET http://localhost:3002/person/3 The number will match id of model.

How to avoid too many model classes

The number of models has grown quickly in my application. I'm wondering about your standard practices regarding backbone.js. Lets say you want to create a view that requires 2 other models. Do you create a new model class to contain the 2 models like this:
var m = new TheModel({
model1: new Model1,
model2: new Model2
});
var view = new TheView({model:m});
or do you just do something like:
var m = {
model1: new Model1,
model2: new Model2
};
var view = new TheView({model:m});
The second seems better because then I don't need the extra model class TheModel. But if I mix the two methods, then in my view I have to remember which style I'm using because if I want to get access to model1 or model2 then there are two different ways:
var m1 = this.model.get('model1');
or this way in the second scheme:
var m1 = this.model.model1;
Which is better in your opinion?? How do you organize all the models and views?
Thanks!
Unless there is a reason to link your models, I would not create a new model that aggregates other models. The second option is better because you are not linking them.
I prefer to separate them even further:
var view = new TheView({purchases: purchasesModel, user: userModel });
Then, inside the view, instead of referencing this.model, you reference this.purchases and this.user specifically.
You see, the model property on the views is really just a convention. There is nothing special about the model property in the view except that the model property will get copied automatically in the constructor. Other than that, there is no reference to the model in Backbone.View.
Of course, this means that you need to do something with it:
var TheView = Backbone.View.extend({
initialize: function(options) {
this.purchases = options.purchases;
this.user = options.user;
}
});
This way, you are being explicit about the multiple models that you require. I like this better than verison #2 because you are not as explicit about the requirements of the View.
You should use Collections in this case. Here you can read more about Collections: http://backbonetutorials.com/what-is-a-collection/

Resources