0

What is the best way to detect the moment after a Backbone View, extended from an other object or not, has been removed?

JsFiddle added : http://jsfiddle.net/simmoniz/M5J8Q/1917/ How to make the line #32 working without altering the views...

<h2>The container</h2>
<div id="container"></div>
<script>
var SomeExtendedView = Marionette.ItemView.extend({
    events: {
        'click button.remove':'remove',   
    },
});
var JohnView = SomeExtendedView.extend({
    template: _.template('<div><p>I\'m a <em>John view</em> <button class="remove">Remove me</button></p></div>'),
});
var DoeView = SomeExtendedView.extend({
    template: _.template('<div><p>I\'m a <strong>Doe view</strong> <button class="remove">Remove me</button>'),
});
var SimpleView = Backbone.View.extend({
    initialize: function(){
        Backbone.View.prototype.initialize.apply(this, arguments);
        this.$el.bind('click', _.bind(this.remove, this));
    },
    render: function(){
     this.$el.html('<div><p>Simple view. <strong>Click on me to remove</strong></p></div>');   
     return this;
    }
});

var container = {
    el: $('#container'),
    views: null,
    add: function(view){
        if(!this.views)this.views = [];
        this.el.append(view.render().el);
        view.$el.bind('remove', _.bind(this.onRemove, this));
    },
    onRemove : function(element){
        console.log('Element ' + element + ' has been removed!');    
    }
}

container.add(new JohnView());
container.add(new DoeView());
container.add(new SimpleView());
</script>
Simmoniz
  • 1,080
  • 15
  • 27
  • http://stackoverflow.com/questions/9513194/backbone-js-fire-event-on-remove Is this what you wanted to know? – Jonathan Lerner Jul 23 '15 at 20:01
  • The link you provided gives a great idea of what I'm looking, thanks. But I look for a way that doesn't alter Backbone's prototype... And I can't rely on extending backbone since I need to detect after a view has been removed, without knowing if it is a backbone or extended backbone view. – Simmoniz Jul 23 '15 at 20:28
  • You can try using jQuery to notify you when the DOM element is removed: http://stackoverflow.com/questions/2200494/jquery-trigger-event-when-an-element-is-removed-from-the-dom – Jonathan Lerner Jul 23 '15 at 20:31
  • 1
    You're supposed to call [`View#remove`](http://backbonejs.org/#View-remove) to remove a view so why can't you override that and trigger whatever events you need? – mu is too short Jul 23 '15 at 20:33
  • I tryed myView.$el.on('remove', _.bind(this.funcToCallOnRemove, this)), and the event does not fire... Maybe Backbone performs some extra cleaning on "el" on remove, which cause event is not firing? mu si too short : That's because the view can be removed by itself, or by a parent. In my case, the parent must perform something when view is removed. – Simmoniz Jul 23 '15 at 20:53
  • I edited the question, there is a jsfiddle. I'd like to make the line #32 working without altering the views – Simmoniz Jul 27 '15 at 17:46

3 Answers3

0

View lifecycle management is one of the important things missing from the backbone core.

All non-trivial apps end up needing to solve this. You can either roll your own, or use something like marionette or Chaplin.

Basically, backbone doesn't have the concept of view destruction or dealocation. A point in time in which listeners should be unbound. This is the single greatest source of memory leaks in backbone apps.

p3drosola
  • 5,784
  • 2
  • 23
  • 30
  • Your answer has potential. I'd appreciate some simplified example (no copy and paste from one or all mentioned libraries/frameworks) how this could look like. – try-catch-finally Apr 28 '16 at 20:20
0

I finally came up with a working solution. Since the element added is a Backbone view (simple or extended), it has remove function. This solution replaces the remove function with a new "remove" event that performs the same operation, but triggers a "remove" event juste before. Listeners can catch it now. It works great :

var ev = new $.Event('remove'),
    orig = $.fn.remove;
view.remove = function() {
    $(this).trigger(ev);
    return orig.apply(this, arguments);
}

Then we can listen to the "remove" event like in my question

view.bind('remove', _.bind(this.onRemove, this));
Simmoniz
  • 1,080
  • 15
  • 27
  • It seems that you extend jQuerys `remove()` function, not Backbones, right? I'm confused that you name that variable `view` and talk in your question about Backbone views. – try-catch-finally Apr 28 '16 at 20:39
-1

Inside the view

events: { "remove" : "some function", },

François Richard
  • 6,817
  • 10
  • 43
  • 78
  • Excuse me sir, but I think this is not correct (or please show me the spec that provides this event for an DOM element and/or provide a Fiddle). There's a deprecated [`MutationEvent` with a `DOMNodeRemoved` type](https://developer.mozilla.org/en-US/docs/Web/API/MutationEvent) and a [`MutationObserver`](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver#Example_usage) that superseeds the former. – try-catch-finally Apr 28 '16 at 20:17