Vasiliy Rusin
Vasiliy Rusin

Reputation: 1122

How to swap a view's template and remove the old view

I have the following code:

switch (type) {
    case "countdown":
        this.render(_this.templates.countdown);
        break;
    case "timer":
        this.render(_this.templates.timer);
        if (App.Views.timer) App.Views.timer.remove();
        App.Views.timer = new Timer();
        break;
}

So, as I suppose when the template were rendered we're remove previous View, because the link on new DOM element changed. But I'm not sure what old view was really removed.

Because if I add console.log(App.Views.timer) after if (App.Views.timer) App.Views.timer.remove(); I get: child {cid: "view3", $el: jQuery.fn.init(1), el: div#timer.timer}. And it's look like nothing changed!

I have two questions.

  1. Is it correct way to remove view from memory?
  2. If I have a div which can change template, is it a correct way to create new View? Unfortunately, the solution to just hide the template does not suit my situation.

Upvotes: 0

Views: 354

Answers (1)

Emile Bergeron
Emile Bergeron

Reputation: 17430

What does the view's remove function do?

View's remove function just removes the element from the DOM while unbinding any DOM related events and Backbone specific events.

Removes a view and its el from the DOM, and calls stopListening to remove any bound events that the view has listenTo'd.

The code for the remove function is:

// Remove this view by taking the element out of the DOM, and removing any
// applicable Backbone.Events listeners.
remove: function() {
  this._removeElement();
  this.stopListening();
  return this;
},

About the view still in memory

So it still lives in memory until you release any references left. Logging the view object to the console keeps it alive as it's a reference to it.

Sharing a div for multiple views

I wouldn't go your way on this. Instead of a switch case, you could use a Backbone Router with routes and then make yourself some kind of layout view.

A super simple layout view could look like this:

var LayoutView = Backbone.View.extend({
    initialize: function() {
        // caching the jQuery object on init
        this.$content = this.$('#content');
    },
    setContent: function(view) {
        var content = this.content;
        if (content) content.remove();
        content = this.content = view;
        this.$content.html(content.render().el);
    },
});

Used within a router:

var Router = Backbone.Router.extend({
    routes: {
        'about': 'aboutRoute',
        'contact': 'contactRoute',
        // put the catch-all last
        '*home': 'homeRoute',
    },
    initialize: function() {
        // create the layout once here
        this.layout = new views.Application({
            el: 'body',
        });
    },
    homeRoute: function() {
        var view = new views.Home();
        this.layout.setContent(view);
    },
    aboutRoute: function() {
        var view = new views.About();
        this.layout.setContent(view);
    },
    contactRoute: function() {
        var view = new views.Contact();
        this.layout.setContent(view);
    }
});

I wrote a detailed answer on how to use a router with a simple layout view.

Upvotes: 2

Related Questions