I've a collectionview
ItineraryEditorView
that is swapped in and out of a layout region.
The same instance of collectionView
is swapped in using region.show
instead of creating new instance for collectioView
every time. The render method on the collection calls delegateEvents()
method.
ItineraryEditorView = Marionette.CollectionView.extend({
tagName: "div",
emptyView: EmptyItineraryDayView,
itemView: ItineraryDayView,
initialize: function (options) {
},
render: function() {
Marionette.CollectionView.prototype.render.apply(this);
this.delegateEvents();
},
});
The view is swapped out by closing region:
plannerLayout.itineraryEditorRegion.close();
Swapping in the view:
itineraryEditorView.delegateEvents();
plannerLayout.itineraryEditorRegion.show(itineraryEditorView);
Deletion of a model is done by listening to the bubbled up event from itemView
to collectionView
(works, no issues here)
itineraryEditorView.on("itemview:delete:day", function(childView, model) {
days.remove(model); //days coll is passed in to coll view on instance creation
holiday.save();
});
I'd expect that this would be enough to ensure the the child itemViews
in the collection view are removed/closed when a model is removed from the underlying days collection. I can see that the collection is actually modified and and saved on the server,however the collection view is not altered.
This scenario of course works when before the collection view is swapped out first time.
The coll. view does update itself after I re-visit another tab and come back to this tab (thus the entire collection is rendered- confirming the change/deletion)
What is the best way get around this issue? If I recreate the instance of collection view, it does cause to lose other "on" handles in the code.
There's no need to call delegateEvents
manually - Backbone does this in the view's constructor. When you close the region, the region will close your view removing all internal references and unbinding all events, preparing it for garbage collection. Once a view has been close()
'd, it should not be used again. The fix to your problem should be to new
up another instance of your ItineraryEditorView
and pass that to the region on show
.
Also, it's not necessary to call region.close()
before calling region.show(view)
; the first thing show
does is to close()
the current view, if any. My recommendation to modify your code as follows:
ItineraryEditorView = Marionette.CollectionView.extend({
// tagName: "div", // <-- unnecessary as written - default tag
emptyView: EmptyItineraryDayView,
itemView: ItineraryDayView
// this empty override is unnecessary as written - recommend removing it
// initialize: function (options) {
// },
// this override is unnecessary as written - remove it:
// render: function() {
// Marionette.CollectionView.prototype.render.apply(this);
// this.delegateEvents();
// },
});
...
// plannerLayout.itineraryEditorRegion.close(); <-- delete this line; it's not needed
// itineraryEditorView.delegateEvents(); <-- ditto
EDITED FROM ORIGINAL POST
// define a delegate to handle events shared across multiple instances of the view:
function handleDeleteChild(childView, model) {
days.remove(model); //days coll is passed in to coll view on instance creation
holiday.save();
});
// create the ItineraryEditorView
// NOTE: As written this will likely conflict with your current code;
// update as required
var itineraryEditorView = new ItineraryEditorView(options);
// bind event listeners to it
itineraryEditorView.on("itemview:delete:day", handleDeleteChild);
// show it
plannerLayout.itineraryEditorRegion.show(itineraryEditorView);