Handlebars with Backbone template not rendering

巧了我就是萌 提交于 2019-12-24 07:43:03

问题


I have an app which uses both Backbone and Handlebars on a server and a client.

Server

Backbone and Express-Handlebars installed

app.js

app.set('views', path.join(__dirname, '/views'));
app.engine('.hbs', expHbs({
  defaultLayout: 'index', 
  extname: '.hbs'
}));
app.set('view engine', '.hbs');

index.js

exports.init = function(req, res){
  res.render('contact/index');
};

index.hbs

<div class="row">
  <div class="col-sm-6">
    <div class="page-header">
      <h1>Send A Message</h1>
    </div>
    <div id="contact"></div>
  </div>
  ....some code

<script id="tmpl-contact" type="text/x-handlebars-template">
  <form>

      bootstrap with handlebars temlates {{....}} in here

  </form>
</script>

Client

On the client I have Backbone and Handlebars installed via Bower

In index.js Backbone.view

var Handlebars = require('handlebars');
  app.ContactView = Backbone.View.extend({
    el: '#contact',
    template: Handlebars.compile( $('#tmpl-contact').html() ),
    events: {
      'submit form': 'preventSubmit',
      'click .btn-contact': 'contact'
   },
    initialize: function() {
      this.model = new app.Contact();
      this.listenTo(this.model, 'sync', this.render);
      this.render();
    },
    render: function() {
      this.$el.html(this.template( this.model.attributes ));
      this.$el.find('[name="name"]').focus();
   },
    preventSubmit: function(event) {
      event.preventDefault();
   },
    contact: function() {
      this.$el.find('.btn-contact').attr('disabled', true);

      this.model.save({
        name: this.$el.find('[name="name"]').val(),
        email: this.$el.find('[name="email"]').val(),
        message: this.$el.find('[name="message"]').val()
      });
    }
  });

What happens is that index.hbs renders on the server-side normally, but it is not rendering a form inside script; it shows empty <div id="contact"></div> and doesn't shows any errors in console.

As shown here Using Handlebars with Backbone, a way to replace underscore templating with handlebars is simply to replace _.template with Handlebars.compile, but neither of these options works for me. I also tried different type attributes for <script> and it's still not working.

How can I fix this? Any help is appreciated. Thanks.

Added full index.js on client

/* global app:true */

var Handlebars = require('Нandlebars');

(function() {
  'use strict';

  app = app || {};

  app.Contact = Backbone.Model.extend({
    url: '/contact/',
    defaults: {
      success: false,
      errors: [],
      errfor: {},
      name: '',
      email: '',
      message: ''
    }
  });

  app.ContactView = Backbone.View.extend({
    el: '#contact',
    template: Handlebars.compile( $('#tmpl-contact').html() ),
    events: {
      'submit form': 'preventSubmit',
      'click .btn-contact': 'contact'
    },
    initialize: function() {
      this.model = new app.Contact();
      this.listenTo(this.model, 'sync', this.render);
      this.render();
    },
    render: function() {
      this.$el.html(this.template( this.model.attributes ));
      this.$el.find('[name="name"]').focus();
    },
    preventSubmit: function(event) {
      event.preventDefault();
    },
    contact: function() {
      this.$el.find('.btn-contact').attr('disabled', true);

      this.model.save({
        name: this.$el.find('[name="name"]').val(),
        email: this.$el.find('[name="email"]').val(),
        message: this.$el.find('[name="message"]').val()
          });
        }
     });

  $(document).ready(function() {
    app.contactView = new app.ContactView();
  });
}());

回答1:


So as mentioned here Handlebars.compile must load after handlebars template in <script></script> is loaded into the DOM. In this case when using express-hanldebars, a link to js file must be placed after {{{ body }}} element in the main layout. That is the right answer.

There is one more problem here that app can't be defined globally as it appears in index.js

In order to define app globally you have to move app = app || {}; outside the IIFE scope and put it at the beginning of a file and declare it as a global variable: var app = app || {};. If there are multiple backbone files they should all implement a similar structure in order to app be global.



来源:https://stackoverflow.com/questions/42335681/handlebars-with-backbone-template-not-rendering

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!