0

My app contains two views with templates, router, model and collection.

root
 js
  collections
   -collection.js
  models
   -model.js
  routers
   -router.js
  templates
   -add_item.html
   -list.html
  views
    -add_item.js
    -list.js
index.html

In router.js, I'm trying to navigate to a child view.

define([
    'jquery',
    'backbone',
    'views/item'
], function($, Backbone, ItemView) {
    'use strict';

    return Backbone.Router.extend({
        routes: {
            '': 'list',
            'list/add': 'addItem',
            'list/edit/:id': 'editItem'
        },

        addItem: function() {
            new ItemView();
        }
    });
});

By looking at the call stack, I see that my router triggers. But the template of my child view doesn't initializes.

item.js code:

return Backbone.View.extend({
    template: _.template(itemTemplate),

    events: {
        'click #save': 'saveItem',
        'click #cancel': 'cancel'
    },

    initialize: function() {
        this.render();
    },

    render: function() {
        this.$el.html(this.template);
        return this;
    }
});
fasenberg
  • 2,735
  • 3
  • 10
  • 16

1 Answers1

1

Underscore's _.template

Underscore _.template function takes a template string as argument (and optionally a settings object) and returns a new pre-compiled template function which can take an object as an argument.

template: _.template(itemTemplate), // this returns a function, which is fine here.

This line is fine, but the following one puts the returned function as the HTML content:

this.$el.html(this.template); // a function reference as HTML?!

You need to call the pre-compiled template function to get the string:

this.$el.html(this.template());

Backbone view rendering

Now that the view's default root element (el) is correctly filled with the template content.

<div>The div element is the default root element, this text is the template</div>

But once the template is rendered, the view's element is still not in the page. To make it part of the page, you could:

  • put the view's el manually into another element in the router

    addItem: function() {
        var view = new ItemView();
        $("#content").html(view.render().el);
    }
    

    I put view.render() here because rendering in the initialize is not my preferred pattern as it's limiting the reuse of the view. But it really depends on what's the view for.

  • pass a selector string or element to the el constructor option of the view

    new ItemView({ el: '#the-view-element-id' });
    
  • create the view with a hard-coded el property (this can be overridden by the el option above)

    Backbone.View.extend({
        el: '#the-view-element-id',
        /* ... */
    

Default route

If you want to default to the list route, you could make the routes object like this:

routes: {
    'list/add': 'addItem',
    'list/edit/:id': 'editItem'
    // catch-all (default) route at the end
    '*anything': 'list',
},

Additional information:

Community
  • 1
  • 1
Emile Bergeron
  • 17,074
  • 5
  • 83
  • 129
  • Thanks, it's help. But add_item.js view render with list.js view together at same screen. I want only child view add_item template render on list/add and list/edit/:id routes – fasenberg Dec 19 '16 at 12:54
  • @Gastello you need to take the information from my answer and apply it to your situation. It can't work out of the box, it's only techniques and general information to answer the question. I can't guess what you're trying to do without a clear [mcve]. – Emile Bergeron Dec 19 '16 at 15:26
  • @Gastello take a look at [TodoMVC](http://todomvc.com/). There's a demo of [Backbone+Require](http://todomvc.com/examples/backbone_require/) ([source](https://github.com/tastejs/todomvc/tree/gh-pages/examples/backbone_require)). – Emile Bergeron Dec 19 '16 at 18:24
  • I saw an example of this, but in my case there are 3 states. And I have just the problem with displaying relevant templates depending on each state. – fasenberg Dec 19 '16 at 18:33
  • @Gastello editing and creating is often the same view. I personally reuse the same form view to create and edit data. If you understand correctly the Todo example, you'll be able to implement what you want with Backbone with ease. – Emile Bergeron Dec 19 '16 at 18:35
  • Could i add you to collaborators to my repository and help me fix problem? – fasenberg Dec 19 '16 at 18:48
  • @Gastello I try to answer to most Backbone questions on SO, but I have a job and many other personal projects so I can't invest myself in everyone's project. Anyway, it's not a specific bug that you're trying to fix, it's a project you're trying to accomplish. The solution is to read on Backbone design patterns and techniques, tips and tricks. There are a lot of great tutorials, blog posts and already asked questions on SO to get started quickly. Good luck ;) – Emile Bergeron Dec 19 '16 at 18:56