Reputation: 1624
Is there a way so that the ItemViews contained in a CompositeView only render on say clicking a button? I would like a change in the collection to update the Composite View's dom but each individual ItemView should not render until required.
Pardon me if I'm a little vague in my description but I have very limited knowledge of backbone and marionette.
Upvotes: 0
Views: 543
Reputation: 5053
As you well know, Marionette is eager to take your Composite (or Collection) View's children views and spawn them. That's why included in the Composite View render
method is the _renderChildren
process. Once invoked, there's really no way to selectively render children views.
But there's a back door that gets around rendering your entire collection. It's a simple as initializing
your Composite View with an empty collection, like this
//Define MyCollection` and MyCompositieView and then...
var myCollection = new MyCollection(); // Construct an empty collection
var myCompositeView = new MyCompositeView({ collection: myCollection });
An "empty" Composite View will render its own template normally, and simply skip _renderChildren
.
You can then wire an event to call myCompositeView.collection.add(model)
. You'll notice that Marionette listens for an add
event on your collection,
_initialEvents: function() {
if (this.collection) {
this.listenTo(this.collection, 'add', this._onCollectionAdd);
// Other _initialEvents methods...
}
},
and _onCollectionAdd
is responsible for rendering the added model:
_onCollectionAdd: function(child) {
this.destroyEmptyView();
var ChildView = this.getChildView(child);
var index = this.collection.indexOf(child);
this.addChild(child, ChildView, index); // The rendering happens here
},
To make this work you'd have to have an array of your models inside your CompositeView, but outside that view's collection. I usually just wire up an $.getJSON
(or any other AJAX method) to get the data and store it in a property of the View object. Say you do this on initialize:
initialize: function() {
var that = this,
dataUrl = "some/url";
$.getJSON(dataUrl, function(data) {
that.myModels = data;
});
},
And, in your Composite View you'd probably have an event, say a click on an element of your Composite view:
events: {
'click button': 'addChild'
}
addChild: function (event) {
// functionality to identify which child to add to the collection
this.collection.add(this.myModels[j]); // Where 'j' is the index the model you want lives in.
});
When addChild
is called the collection adds the proper model, and Mariontte makes sure to render a child view populated with this model.
There variations on how to do this, and you don't have to have an event wired in your view. But I think I proved how you can have methods render independently. If you provide more information I can give you more ideas.
Upvotes: 2