How to check if sidebar view has already been rendered in backbone?

Generally, the user enters the website through the home page and then I render the sidebar view there. Next, the user clicks a link and the router renders another view and replaces the original content view. The sidebar view is not re-rendered.

When the user clicks refresh while on a sub-page, the sidebar is not rendered.

How do I check whether a view exists and has been rendered?

Answers:

Answer

Split the responsibilities and stick to it. Don't put the sidebar rendering into the hands of the home page view.

You could have a layout view which handles rendering the content, header, footer and sidebar. Then, when the user navigate to another page, the router just calls something like setContent(view) on the layout view, which makes sure the sidebar (and everything else) was rendered before rendering the content.

Assuming this template:

<body>
    <div class="header"></div>
    <div class="content"></div>
    <div class="sidebar"></div>
</body>

The layout view could be as simple as:

var Layout = Backbone.View.extend({
    el: 'body' // just for the simple example, let's put this as the body.

    // This avoids repeating selector strings everywhere in the view code.
    // If you change a class name in the template, change it only once here.
    regions: {
        header: '.header',
        content: '.content',
        sidebar: '.sidebar'
    },
    initialize: function(options) {
        var regions = this.regions;

        // I like to "namespace" my sub-views into an object.
        // That way, you still can access them by name, but you can also
        // loop on the sub-views.
        this.views = {
            sidebar: new SideBar({ el: regions.sidebar }),
            header: new Header({ el: regions.header }),
        };

        this.$content = this.$(regions.content);
    },

    render: function() {
        _.invoke(this.views, 'render');
        return this;
    },

    /**
     * Set the content to a view.
     * @param {Backbone.View} view to replace the content with.
     */
    setContent: function(view) {
        var views = this.views,
            content = views.content;
        if (content !== view) {
            if (content) content.remove();
            views.content = content = view;
            this.$content.html(content.render().el);
        }
    },
});

And the router could lazily create views:

var AppRouter = Backbone.Router.extend({
    routes: {
        '*otherwise': 'homepage',
        'specific/:id': 'specificPage'
    },
    initialize: function() {
        this.layout = new Layout();
        this.layout.render();
        this.views = {};
    },
    homepage: function() {
        // These local variables improve minification and readability.
        var views = this.views,
            homepage = views.homepage;
        if (!homepage) {
            views.homepage = homepage = new HomePage();
        }
        this.layout.setContent(homepage);
    },
    specificPage: function(id){
        var views = this.views,
            specific = views.specific;
        if (!specific){
            views.specific = specific = new HomePage();
        }
        specific.setId(id); // hypothetical logic
        this.layout.setContent(specific);
    }
});

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us Javascript

©2020 All rights reserved.