So I'm looking into backboneJS and I'm trying to figure out when to use the collection attribute and when to use this.collection inside the initialize function? Is there a difference? Here is an example.
Backbone.View.extend({
collection: myCollection,
initialize: function(collectionData) {
this.collection = new app.Library(collectionData);
}
});
When you use "this" in a method of a object, it is set to the object the method called on. So this.collection will always equal to collection property (initialize method will be invoked by a view instance right?).
In my opinion, I always assign the default collection in view option declaration and access the collection reference by this.collection in the method of view object.
//set the default collection to a view object
var CustomView = Backbone.View.extend({
collection: myCollection
});
//or set collection when you instantitate a view
var myView = new CustomView({collection: myCollection});
//and get the reference of view's collection for event registering
initialize:function(){
//refresh view when new data is added to collection
this.listenTo(this.collection,"add",this.render);
}
Related
Marionette collectionEvents are not firing when the collection is defined inside the initialize function.
ex:
collectionEvents: {
update: 'onCollectionUpdate',
change: 'onCollectionChange',
error: 'onCollectionError',
},
initialize(opts) {
this.collection = new ListCollection({...});
}
but it works fine when the collection is defined as a property on the compositeView class
collection: new ListCollection({...}),
collectionEvents: {
update: 'onCollectionUpdate',
change: 'onCollectionChange',
error: 'onCollectionError',
},
Is there a reason for this I need to define the collection in the initialize function, because i have data being passed to the constructor that the collection needs
You can just pass in an empty collection to the view so that event bindings happen properly while creating view instance, then populate data in collection. Or just pass in collection including data.
const view = new CollectionView({
collection: new ListCollection(/*data you pass to initialize*/),
});
or in view's initialize
initialize(opts) {
this.collection.reset(options.data);
}
I wouldn't expect marionette to track when you are adding collection property to view at random point in time and then create event bindings accordingly.
I have this collection:
App.Collection.Pieces = Backbone.Collection.extend({
model: App.Model.Piece,
initialize: function() {
this.add(
// The `King` model extends the `Piece` model
new App.Model.King({
cid: 'wk',
color: 'white'
})
);
}
});
Then I have this code in a view:
this.white = new App.Collection.Pieces();
console.log(this.white.get('wk'));
I have two questions:
Can I add a model B to a collection of A models, if B extends A?
The console.log statement returns undefined. Any reason why the cid property is not being set?
Thanks.
You can add any object or model to a collection. If its a plain JS object, the model defined for the collection will be instantiated. Annotated source
According to Backbone's documentation the cid is automatically assigned to all models created. Looking at the annotated source it seems the cid is automatically generated - you cannot assign a custom cid to a model.
Here I am passing a model to a Backbone view.
view = new View ({model:{item:4,name:"Ipad"}});
When I console.log that model from within the View. I get:
Object {item: 4, title: "Ipad"}
This is not a backbone model therefore I don't have methods
like toJSON. I realize that if I define a Backbone model and
passed it in everything works fine.
view = new GenreView ({model:new Model({title: 4, title: "Ipad"})});
This logs
r {cid: "c2", attributes: Object, _changing: false, _previousAttributes: Object, changed: Object…}
Why is it that first approach doesn't work and how can I fix it?
Its simply that the special 'model' option expects a Backbone.Model not a javascript object.
So you are correct when you create a new Backbone.Model to pass into the view.
There is nothing to fix as far as I can tell.
You need to use a Backbone.Model instead of a regular JavaScript object {}
var Item = Backbone.Model.extend({
// ...
});
Instantiate the Item model
var myItem = new Item();
Now use your item in the view
var myView = new View({model: myItem});
This answer assumes that View is setup as something like
var View = Backbone.View.extends({
// ...
});
You could cast the object to a Backbone Model in your view's initialize method:
var View = Backbone.View.extend({
initialize: function(options){
if (_.isPlainObject(this.model)) {
this.model = new Backbone.Model(this.model);
}
}
});
This way the view will be able to operate on it's model regardless of whether you passed it an instance of a Backbone.Model or a plain object. You can see an example of it working here: http://jsbin.com/igecEgE/1/edit?js,console
I have a backbone collection of models.
MyCollection = Backbone.Collection.extend({
model: myMymodel;
});
MyModel = Backbone.Model.extend({
...
});
Each model has a view
myView = Backbone.View.extend({
initialize: function() {
this.model = new MyModel();
};
});
There is no persistence on the server-side. This is just for structuring client-side information. So the models do not have ids, and a url for Backbone.sync has not been configured.
From within the view, I want to remove the model from the collection.
I have tried the following:
this.model.trigger( "destroy" );
However it does not work. The destroy event is not propagating to the collection.
Any idea what I'm doing wrong?
Thanks,
I think you are not instantiating the collection at all. Cant make out that from the code at least. If you are just creating a model instance but not adding it to any collection, this.model.trigger("destroy"); will do nothing.
myView = Backbone.View.extend({
initialize: function() {
this.coll = new MyCollection();
this.model = new MyModel();
this.coll.add(this.model);
};
});
Now that the model is part of the collection:
this.model.destroy()
Makes a delete api call and gets removed from the collection
this.collection.remove(this.model)
Removes the model from the collection but does not make a delete api call.
this.model.trigger("destroy");
Triggers a destroy event on the model but does not destroy the model as such. sames as collection.remove(this.model) if model is part of the collection.
collection.remove(model) would be a more appropriate function to use since you're not persisting your models on the server-side. Backbone.Collection.remove
I have a Marionette.CompositeView which needs to render a collection.
I would like to filter this collection on fetch and add action.
I tried with the following code (1) but I get the following error (2).
Any ideas, thanks.
(1)
var myCompositeView = Marionette.CompositeView.extend({
initialize: function () {
this.collection = app.taskCollection.where({type: 'todo'});
}
});
(2)
// Uncaught TypeError: Object has no method 'on'
Marionette's CompositeView and CollectionView both expect the collection setting to be a valid Backbone.Collection. The where method on Backbone's collection does not return a Backbone.Collection, it return an array. So you have to wrap a collection around the results:
initialize: function(){
var filtered = app.taskCollection.where({type: 'todo'});
this.collection = new Backbone.Collection(filtered);
}
Of course you can use any type that extends from Backbone.Collection. I just wanted to illustrate the point of it being a collection with this example.