Question

I am trying to build a simple crud application with a view of an item and the a listView containing that item view, built from a collection. I want to have a detailView for a specific item, but when switching to this detailView, I do not know how to dispose of the listView properly. I have seen solutions for removing zombies on a single view, but not for a view composed of a collection. Is there any straight forward way to clean up a List view composed of views?

var Model = Backbone.Model.extend({
defaults : {
    id : '',
    name : ''
}

});
var Collection = Backbone.Collection.extend({
model : Model
})
var HomeView = Backbone.View.extend({
tagName : "div",
id : "home-view",
initialize : function() {
    $("body").html(this.el);
    this.render();
},
render : function() {
    this.$el.html("<h1>This is the home page</h1><a href='#users'>Go to users</a>");
}
});

var UserView = Backbone.View.extend({
tagName : "li",
initialize : function(e) {

    _.bindAll(this, "alertName");
    this.render();
},
events : {
    "click" : "alertName"
},
render : function() {
    this.$el.html("Hi, my name is " + this.model.get('name'));
},
alertName : function() {
    alert(this.model.get('name'));
}
});
var UsersView = Backbone.View.extend({
tagName : "ul",
id : "users-list",
subViews : [],
initialize : function(e) {
    $("body").html(this.el);
    this.collection = new Collection([{
        id : '4',
        name : 'candy'
    }, {
        id : '2',
        name : 'soap'
    }, {
        id : '3',
        name : 'pepper'
    }]);
    console.log(this.collection)

    this.render();
},
render : function() {
    var self = this;
    this.collection.forEach(function(model) {

        var cView = new UserView({
            model : model
        })
        self.subViews.push(cView);
        self.$el.append(cView.el);
    })

    this.$el.after("<a href='#home'>Go to home</a>");
},
close : function() {

    while (this.subViews.length) {
        this.subViews.pop().remove();

    }

    this.remove();
}
});
var Router = Backbone.Router.extend({
routes : {
    "" : "home",
    "home" : "home",
    "users" : "users"
},
initialize : function(options) {
    console.log('router')

 },

  home : function(e) {
     console.log('home')
     this.loadView(new HomeView());

 },
users : function(e) {
    console.log('users');
      this.loadView(new UsersView());

},
loadView : function(view) {
    this.view && (this.view.close ? this.view.close() : this.view.remove());
    this.view = view;
}
});
$(document).ready(function() {

var router = new Router();
Backbone.history.start({

});
});
Was it helpful?

Solution

In the past this is what I've done:

Basically what you'll want to do is keep track of them when creating these new ItemViews. On your ItemsView create a hash of children keyed on model.cid or something (for quick lookup) or just an array of views.

Place a remove function on your ItemsView that when called will call up to the super Backbone.View#remove and loop through the children and call remove on each of them.

You can also put a removeItemView method on your Itemsview that takes a model and looks it up in your children and then calls remove on it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top