Backbone.Collection get first n as new collection - javascript

I have a Backbone.Collection which has been set up like so:
let col = new Backbone.Collection();
let model1 = new Backbone.Model();
model1.set('name', 'first');
col.add(model1);
let model2 = new Backbone.Model();
model2.set('name', 'second');
col.add(model2);
let model3 = new Backbone.Model();
model3.set('name', 'third');
col.add(model3);
When I attempt to select the first 2 models from the collection with this:
let firstTwo = col.first(2);
firstTwo contains model1 and model2 as an array.
How can I get the first two as a Backbone.Collection without manually adding them all to a new collection?

You have to create a new Collection & add them. The good news is creating a new collection is very inexpensive, and the model instances will be the same ones in both the full and partial collection.
Collections automatically have some Underscore methods built into them. But these method all return arrays of Model objects. If you want to instead get a Collection instance, your best bet is to create another method on your Collection class. You can still use the Underscore methods to do the filtering, however.
var MyCollection = Backbone.Collection.extend({
// ...
firstAsCollection: function(numItems) {
var models = this.first(numItems);
return new MyCollection(models);
}
});

You could create a function inside your col model that should behave something like the following:
sublist: function (numberOfElements) {
var i = 0;
return this.filter(function (model) {
if (i <= numberOfElements){
return true;
}
return false;
});
}

Related

Backbone collection toJSON returning collection object

I have a model, which has a backbone collection as one of its attributes.
If I output the model, I can see the collection and all looks ok.
If I output the result of the collection toJSON(), it apparently outputs the whole of the collection object as json.
So the following two lines:
console.log('about to sync', model);
console.log('files', model.attributes.files.toJSON());
Gives the following output:
As you can see, the collection is present and correct in the model, but the toJSON call returns all of the functions in the object as well as the models and so on, instead of "an array containing the attributes hash of each model in the collection"
Backbone doesn't handle sub models/collections by default, you have to plug in your desired behavior. In your case, you just have to override toJSON on your model to replace the collection by its array representation.
Something like
var M = Backbone.Model.extend({
toJSON: function() {
var json = Backbone.Model.prototype.toJSON.call(this);
json.files = this.get('files').toJSON();
return json;
}
});
And a demo http://jsfiddle.net/nikoshr/1jk8gLz4/
Or if you prefer a more general change, alter Backbone.Model.prototype.toJSON to include this behaviour for all models. For example
(function () {
var originalMethod = Backbone.Model.prototype.toJSON;
Backbone.Model.prototype.toJSON = function(options) {
var json = originalMethod.call(this, options);
_.each(json, function(value, key) {
if ((value instanceof Backbone.Collection) ||
(value instanceof Backbone.Model))
json[key] = value.toJSON();
});
return json;
};
})();
http://jsfiddle.net/nikoshr/1jk8gLz4/2/
Tom, You will need to loop through each element in the object to see the contents after you have done toJSON(). I have also faced same problem. See how to parse the JSON object. While printing there would be any issues.
Hope this helps!!
Thanks
override toJSON method.
var yourModel = Backbone.Model.extend({
toJSON: function(){
var base = Backbone.Model.prototype.toJSON.call(this);
for (key in base) {
item = base[key];
if (item.toJSON != null) {
base[key] = item.toJSON();
}
}
return base;
}
});

Can't get a views/collection to show?

I can't seem to get a test backbone.js app working and I have no idea what I am doing wrong.
http://jsbin.com/iwigAtah/1/edit
I modified your code a little bit and here's what I came up with.
// Backbone Objects
var Item = Backbone.Model.extend({});
var List = Backbone.Collection.extend({
model: Item
});
var ListView = Backbone.View.extend({
initialize: function(options){
// collection is now passed in as an argument
// this line isn't necessary but makes it easier to understand what is going on
this.collection = options.collection;
console.log(this.collection.models);
}
});
// Create a new empty collection
var test = new List();
// Create a new item model and add it to the collection
var testItem = new Item();
test.add(testItem);
// Create a view with your new collection
var g = new ListView({
collection: test
});
The main issue you were having is that you weren't actually adding your model to the collection.

Backbone: Id not being set to model

I have tried the following to set an id to my model:
var globalCounter = 1;
var Model = Backbone.Model.extend({
initialize: function () {
this.id = globalCounter;
globalCounter += 1;
}
});
myModel = new Model();
console.log(myMode.get('id')); // prints undefined
How can I set an id to my models?
You need to use the set() function instead (http://jsbin.com/agosub/1/);
var globalCounter = 1;
var Model = Backbone.Model.extend({
initialize: function () {
this.set('id', globalCounter);
globalCounter += 1;
}
});
myModel = new Model();
console.log(myModel.get('id')); // prints 1
You must use :
this.set('id', globalCounter);
instead of this.id = globalCounter;
You are adding the id value to the Model object, but you want to add it to Model.attributes object. And that what is doing Model.set() method.
model.set("key", value) will put the value in model.attributes.key;
model.get("key") will return the value inside model.attributes.key
This is a little weird for new comers to Backbone, but it's a major (and easy) point to get. It's designed so that using model.set(...) will fire change events you can easily catch to update your views.
Backbone and ES6 Update :
The Backbone attribute object is outdates by ES6 getters and setters. Theses functions can overwrite the standard access.
Warning : this is pseudo-code that may be one day used with ES6 !
class MyModel extends Backbone.Model{
get id(){ return this.attributes.id; }
set id(id){ this.attributes.id = id; }
}
This would allow to write :
let myModel = new Model();
myModel.id = 13; // will use myModel.id(13)
console.log (myModel.id); // will show myModel.id()
As of today, this is only a dream of a Backbone 2. After basic searches, I've seen nothing about that coming.

Get a Backbone View's Parent class from an instance

I am implementing a system where I manage view switching in order to clear any events carried by that view before rendering another. However, I need to look up the view in an array using an instance of the view. How can I get the view class of a view instance?
eg:
var myView = new MyView;
return myView.parent(); // this should return MyView
Thanks!
Sounds like you're looking for the constructor property:
Returns a reference to the Object function that created the instance's prototype.
So if you do this:
var v = new View;
then v.constructor will be View. And if you do this:
var views = [
Backbone.View.extend({}),
Backbone.View.extend({}),
Backbone.View.extend({})
];
var v = new views[1];
for(var i = 0; i < views.length; ++i)
if(v.constructor === views[i])
console.log(i)
You'll get 1 in the console. Demo: http://jsfiddle.net/ambiguous/EgURK/
The way I solve this is to pass in this as part of the constructor and set an "instance variable" inside of the view.
You'd then wire up a getter function with the name "parent" to return it a la your example code:
var myView = new MyView( this );
return myView.parent();

How to call model's method from collection in backbone.js?

I've been trying to learn backbone.js these days. What I've is a model and a collection. The model has some default properties defined in it which I want to fetch within a collection. This is my code:
var model = Backbone.Model.extend({
defaults : {
done : true
}
});
var collection = Backbone.Collection.extend({
model : model,
pickMe : function () {
log(this.model.get('done')); //return undefined
}
});
var col = new collection();
col.pickMe();
How do I call methods defined in my model from collection? Am I doing wrong here?
The basic setup of Backbone is this :
You have models which are part of collection(s). So here in your setup you have a model constructor model and collection constructor collection, but you have no models in your collection and if you have any models they will be an array, so your code should be something like this
var model = Backbone.Model.extend({
defaults : {
done : true
}
});
var collection = Backbone.Collection.extend({
model : model,
pickMe : function () {
for ( i = 0; i < this.models.length; i++ ) {
log(this.models[i].get('done')); // this prints 'true'
}
}
});
// Here we are actually creating a new model for the collection
var col = new collection([{ name : 'jack' }]);
col.pickMe();
You can check the working jsFiddle here : http://jsfiddle.net/S8tHk/1/
#erturne is correct, you're trying to call a method on your model constructor, not a model instance. That doesn't make sense.
If you really want to define methods on the collection, then #drinchev provides an example of how to iterate through the models in the collection and invoke their methods. Although, the example is rather clunky -- using the built-in iterator methods would be more elegant.
Depending what you're trying to accomplish, you may want to just use the built-in collection iterator methods to invoke methods on each model instead of defining methods on the collection. E.g.:
var Model = Backbone.Model.extend({
defaults : {
done : true
}
});
var Collection = Backbone.Collection.extend({
model : Model
});
var col = new Collection([{}, {done : false}, {}]);
col.each(function (model) {
log(model.get('done'));
});
I think you'd better attach your model methods to the model itself, not in the collection. So you should have somethings like this:
var model = Backbone.Model.extend({
defaults : {
done : true
},
pickMe : function () {
log(this.get('done'));
}
});
var collection = Backbone.Collection.extend({
model : model,
});
var model = collection.get(id)
model.pickMe()

Categories

Resources