1
votes

I have the following Todos app in Backbone:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <title>Hello World in Backbone.js</title>
  <style type='text/css'>
    #todoapp ul {
      list-style-type: none;
    }
    #todo-list input.edit {
      display: none;
    }
    #todo-list .editing label {
      display: none;
    }
    #todo-list .editing input.edit {
      display: inline;
    }
  </style>
</head>
<body>

  <section id='todoapp'>
    <header id='header'>
      <h1>Todos</h1>
      <input id='new-todo' placeholder='What needs to be done?'>
    </header>
    <section id='main'>
      <ul id='todo-list'></ul>
    </section>
  </section>

  <script type='text/x-handlebars-template' id='item-template'>
    <div class='view'>
      <input class='toggle' type='checkbox'>
      <label>{{ title }} </label>
      <input class='edit' value='{{ title }}'>
      <button class='destroy'>remove</button>
    </div>
  </script>

  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/javascript"></script>
  <script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.3.3/underscore-min.js" type="text/javascript"></script>
  <script src="http://cdnjs.cloudflare.com/ajax/libs/backbone.js/0.9.2/backbone-min.js" type="text/javascript"></script>
  <script src="http://cdnjs.cloudflare.com/ajax/libs/handlebars.js/1.3.0/handlebars.amd.js" type="text/javascript"></script>
  <script src="http://cdnjs.cloudflare.com/ajax/libs/backbone-localstorage.js/1.0/backbone.localStorage-min.js" type="text/javascript"></script>

  <script type="text/javascript">
    var App = {
      Models: {},
      Collections: {},
      Views: {}
    }

    App.Models.Todo = Backbone.Model.extend({
      defaults: {
        title: '',
        completed: false
      }
    });

    App.Collections.TodoList = Backbone.Collection.extend({
      model: App.Models.Todo,
      localStorage: new Store('backbone-todo')
    });

    App.Views.Todo = Backbone.View.extend({
      tagName: 'li',
      template: Handlebars.compile($('#item-template').html()),
      render: function(){
        this.$el.html(this.template(this.model.toJSON()));
        this.input = this.$('.edit');
        return this;
      },
      initialize: function(){
        this.model.on('change', this.render, this);
        this.model.on('destroy', this.remove, this);
      },
      events: {
        'dblclick label': 'edit',
        'keypress .edit': 'updateOnEnter',
        'blur .edit': 'close',
        'click .toggle': 'toggleCompleted',
        'click .destroy': 'destroy'
      },
      edit: function(){
        this.$el.addClass('editing');
        this.input.focus();
      },
      updateOnEnter: function(e){
        if(e.which == 13){
          this.close();
        }
      },
      close: function(){
        var value = this.input.val().trim();
        if(value){
          this.model.save({title: value});
        }
        this.$el.removeClass('editing');
      },
      toggleCompleted: function(){
        this.model.toggle();
      },
      destroy: function(){
        this.model.destroy();
      }
    });

    App.Views.TodoList = Backbone.View.extend({
      el: '#todoapp',
      initialize: function() {
        this.input = this.$('#new-todo')
        this.collection.on('add', this.addOne, this);
        this.collection.on('reset', this.addAll, this);
        this.collection.fetch();
      },
      events: {
        'keypress #new-todo': 'createTodoOnEnter'
      },
      createTodoOnEnter: function(e) {
        if(e.which !== 13 || !this.input.val().trim()){
          return;
        }
        this.collection.create(this.newAttributes());
        this.input.val('');
      },
      addOne: function(todo){
        var view = new App.Views.Todo({model: todo});
        $('#todo-list').append(view.render().el);
      },
      addAll: function(){
        this.$('#todo-list').html('');
        this.collection.each(this.addOne, this);
      },
      newAttributes: function(){
        return {
          title: this.input.val().trim(),
          completed: false
        }
      }
    });
    var todoList = new App.Collections.TodoList();
    var todoListView = new App.Views.TodoList({collection: todoList});
  </script>

</body>
</html>

But when I open the html file in my browser, the template placeholders are not populate with the data. It shows {{ title }} instead of the actual title. What am I missing here?

PS: I'm seeing the following 2 errors in the console: 1. Uncaught ReferenceError: define is not defined (in handlebars.amd.js)

  1. Uncaught ReferenceError: Handlebars is not defined (on line

    Handlebars.compile($('#item-template').html()))

1
Ain't you missing requirejs? It seems like your version of handlebars try to define itself as a module somehow using requirejs define method...user18428
Or use the non amd version as @wheaties suggestsuser18428

1 Answers

0
votes

I was importing the amd version of handlebars, I removed '.amd' from the cdn url and that resolved the issue.