I'm trying to set animations on rendering and closing an ItemView with Backbone.Marionette. For rendering a view, this is fairly simple:
MyItemView = Backbone.Marionette.View.extend({
...
onRender: function() {
this.$el.hide().fadeIn();
}
...
});
This will have my view fade in when I render it. But let's say I want to fade out my view upon close.
beforeClose: function() {
this.$el.fadeOut(); // doesn't do anything....
}
This won't work, because the item closes immediately after calling this.beforeClose()
, so the animation doesn't have time to complete.
Is there any way, using Marionette as it stands, to accomplish a closing animation?
Alternatively, this is the workaround I've been using:
_.extend(Backbone.Marionette.ItemView.prototype, {
close: function(callback) {
if (this.beforeClose) {
// if beforeClose returns false, wait for beforeClose to resolve before closing
// Before close calls `run` parameter to continue with closing element
var dfd = $.Deferred(), run = dfd.resolve, self = this;
if(this.beforeClose(run) === false) {
dfd.done(function() {
self._closeView(); // call _closeView, making sure our context is still `this`
});
return true;
}
}
// Run close immediately if beforeClose does not return false
this._closeView();
},
// The standard ItemView.close method.
_closeView: function() {
this.remove();
if (this.onClose) { this.onClose(); }
this.trigger('close');
this.unbindAll();
this.unbind();
}
});
Now I can do this:
beforeClose: function(run) {
this.$el.fadeOut(run); // continue closing view after fadeOut is complete
return false;
},
I'm new to using Marionette, so I'm not sure if this is the best solution. If this is the best way, I'll submit a pull request, though I'll want to put a bit more thought into how this could work with other types of views.
This could potentially be used for other purposes, such as asking for confirmation on close (see this issue), or running any kind of asynchronous request.
Thoughts?