2014-01-07 4 views
0

나는 백본에서 Todo 응용 프로그램을 수행 중입니다. 샘플은 밑줄 템플릿이지만, hogan 템플릿과 함께 백본을 사용하려고합니다. 그 좋은 컴파일,하지만 렌더링 작동하지 않습니다. 그것은 발생 오류 .. catch되지 않은 형식 오류를 : 객체의 속성 '템플릿'[개체 개체]이 내 JS 파일입니다 함수잡히지 않은 TypeError : 객체 [object Object]의 'template'속성이 함수가 아닙니다.

되지 않습니다 : 이것은 내 html로입니다

var app = app || {}; 

(function ($) { 
    'use strict'; 

    // Todo Item View 
    // -------------- 
    _.templateSettings = { 
       evaluate : /\{\[([\s\S]+?)\]\}/g, 
       interpolate : /\{\{([\s\S]+?)\}\}/g 
      }; 
    app.TodoView = Backbone.View.extend({ 
     //... is a list tag. 
     tagName: 'li', 

     template: Hogan.compile($('#item-template').html()), 

     // The DOM events specific to an item. 
     events: { 
      'click .toggle': 'toggleCompleted', 
      'dblclick label': 'edit', 
      'click .destroy': 'clear', 
      'keypress .edit': 'updateOnEnter', 
      'keydown .edit': 'revertOnEscape', 
      'blur .edit': 'close' 
     }, 

     initialize: function() { 
      this.listenTo(this.model, 'change', this.render); 
      this.listenTo(this.model, 'destroy', this.remove); 
      this.listenTo(this.model, 'visible', this.toggleVisible); 
     }, 

     render: function() { 
      if (this.model.changed.id !== undefined) { 
       return; 
      } 
      //_.each(myAlbum,function(album) { 
      // this.el.append(template.render(album.toJSON())); 
      //}); 
      console.log(Hogan.compile($('#item-template').html())); 

        this.$el.html(this.template(this.model.toJSON())); 
        // Error in the above line 

      this.$el.toggleClass('completed', this.model.get('completed')); 
      this.toggleVisible(); 
      this.$input = this.$('.edit'); 
      return this; 
     }, 

     toggleVisible: function() { 
      this.$el.toggleClass('hidden', this.isHidden()); 
     }, 

     isHidden: function() { 
      var isCompleted = this.model.get('completed'); 
      return (// hidden cases only 
       (!isCompleted && app.TodoFilter === 'completed') || 
       (isCompleted && app.TodoFilter === 'active') 
      ); 
     }, 

     toggleCompleted: function() { 
      this.model.toggle(); 
     }, 

     edit: function() { 
      this.$el.addClass('editing'); 
      this.$input.focus(); 
     }, 

     close: function() { 
      var value = this.$input.val(); 
      var trimmedValue = value.trim(); 

      if (!this.$el.hasClass('editing')) { 
       return; 
      } 

      if (trimmedValue) { 
       this.model.save({ title: trimmedValue }); 

       if (value !== trimmedValue) { 
        this.model.trigger('change'); 
       } 
      } else { 
       this.clear(); 
      } 

      this.$el.removeClass('editing'); 
     }, 

     updateOnEnter: function (e) { 
      if (e.which === ENTER_KEY) { 
       this.close(); 
      } 
     }, 

     revertOnEscape: function (e) { 
      if (e.which === ESC_KEY) { 
       this.$el.removeClass('editing'); 
      } 
     }, 

     clear: function() { 
      this.model.destroy(); 
     } 
    }); 
})(jQuery); 

<!doctype html> 
<html lang="en"> 
<head> 
<meta http-equiv="content-type" content="text/html; charset=UTF-8"> 
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> 
    <title>Backbone.js • TodoMVC</title> 
<link rel="stylesheet" href="js/assets/base.css"> 
</head> 
<body> 
    <section id="todoapp"> 
    <header id="header"> 
     <h1>todos</h1> 
     <input id="new-todo" placeholder="What needs to be done?" autofocus> 
    </header> 
    <section id="main"> 
     <input id="toggle-all" type="checkbox"> 
     <label for="toggle-all">Mark all as complete</label> 
     <ul id="todo-list"></ul> 
    </section> 
    <footer id="footer"></footer> 
    </section> 
    <div id="form-horizontal"> 
    <p>Double-click to edit a todo</p> 
    <p>Written by <a href="https://github.com/addyosmani">Addy Osmani</a></p> 
    <p>Part of <a href="http://todomvc.com">TodoMVC</a></p> 
    </div> 

    <script type="text/template" id="item-template"> 
    <div class="view"> 
     <input class="toggle" type="checkbox" {{ completed ? 'checked' : '' }}> 
     <label>{{ title }}</label> 
     <button class="destroy"></button> 
    </div> 
    <input class="edit" value="{{ title }}"> 
    </script> 

    <script type="text/template" id="stats-template"> 
    <span id="todo-count"><strong>{{ remaining }}</strong> {{ remaining === 1 ? 'item' : 'items' }} left</span> 
    <ul id="filters"> 
     <li> 
     <a class="selected" href="#/">All</a> 
     </li> 
     <li> 
     <a href="#/active">Active</a> 
     </li> 
     <li> 
     <a href="#/completed">Completed</a> 
     </li> 
    </ul> 
    {[ if (completed) { ]} 
    <button id="clear-completed">Clear completed ({{ completed }})</button> 
    {[ } ]} 
    </script> 

    <script src="js/lib/base.js"></script> 
    <script src="js/lib/hogan-2.0.0.js"></script> 
    <script src="js/lib/jquery.js"></script> 
    <script src="js/lib/underscore.js"></script> 
    <script src="js/lib/backbone.js"></script> 
    <script src="js/lib/backbone.localStorage.js"></script> 
    <script src="js/models/todo.js"></script> 
    <script src="js/collections/todos.js"></script> 
    <script src="js/views/todos.js"></script> 
    <script src="js/views/app.js"></script> 
    <script src="js/routers/router.js"></script> 
    <script src="js/app.js"></script> 
</body> 
</html> 

정말 대단 했어. 하지만 새로운 할일을 추가 할 다른 js 파일이 있습니다. 또한 오류가 발생합니다. 잡히지 않은 TypeError : 정의되지 않은의 'toJSON'메서드를 호출 할 수 없습니다. 나는 이것에 아주 새롭다 나를 도우십시오. 내 다른 JS 파일 :

var app = app || {}; 

(function ($) { 
    'use strict'; 



    _.templateSettings = { 
       evaluate : /\{\[([\s\S]+?)\]\}/g, 
       interpolate : /\{\{([\s\S]+?)\}\}/g 
      }; 
    // The Application 
    // --------------- 

    // Our overall **AppView** is the top-level piece of UI. 
    app.AppView = Backbone.View.extend({ 

     // Instead of generating a new element, bind to the existing skeleton of 
     // the App already present in the HTML. 

     el: '#todoapp', 

     // Our template for the line of statistics at the bottom of the app. 

     //statsTemplate: _.template($('#stats-template').html()), 
     statsTemplate:Hogan.compile($('#stats-template').html()), 

     // Delegated events for creating new items, and clearing completed ones. 
     events: { 
      'keypress #new-todo': 'createOnEnter', 
      'click #clear-completed': 'clearCompleted', 
      'click #toggle-all': 'toggleAllComplete' 
     }, 

     // At initialization we bind to the relevant events on the `Todos` 
     // collection, when items are added or changed. Kick things off by 
     // loading any preexisting todos that might be saved in *localStorage*. 
     initialize: function() { 
      this.allCheckbox = this.$('#toggle-all')[0]; 
      this.$input = this.$('#new-todo'); 
      this.$footer = this.$('#footer'); 
      this.$main = this.$('#main'); 
      this.$list = $('#todo-list'); 

      this.listenTo(app.todos, 'add', this.addOne); 
      this.listenTo(app.todos, 'reset', this.addAll); 
      this.listenTo(app.todos, 'change:completed', this.filterOne); 
      this.listenTo(app.todos, 'filter', this.filterAll); 
      this.listenTo(app.todos, 'all', this.render); 

      // Suppresses 'add' events with {reset: true} and prevents the app view 
      // from being re-rendered for every model. Only renders when the 'reset' 
      // event is triggered at the end of the fetch. 
      app.todos.fetch({reset: true}); 
     }, 

     // Re-rendering the App just means refreshing the statistics -- the rest 
     // of the app doesn't change. 
     render: function() { 
      var completed = app.todos.completed().length; 
      var remaining = app.todos.remaining().length; 

      if (app.todos.length) { 
       this.$main.show(); 
       this.$footer.show(); 

       this.$el.html(this.template.render(this.model.toJSON())); 

       this.$footer.html(this.statsTemplate.render({ 
        completed: completed, 
        remaining: remaining 
       })); 

       this.$('#filters li a') 
        .removeClass('selected') 
        .filter('[href="#/' + (app.TodoFilter || '') + '"]') 
        .addClass('selected'); 
      } else { 
       this.$main.hide(); 
       this.$footer.hide(); 
      } 

      this.allCheckbox.checked = !remaining; 
     }, 

     // Add a single todo item to the list by creating a view for it, and 
     // appending its element to the `<ul>`. 
     addOne: function (todo) { 
      var view = new app.TodoView({ model: todo }); 
      this.$list.append(view.render().el); 
     }, 

     // Add all items in the **Todos** collection at once. 
     addAll: function() { 
      this.$list.html(''); 
      app.todos.each(this.addOne, this); 
     }, 

     filterOne: function (todo) { 
      todo.trigger('visible'); 
     }, 

     filterAll: function() { 
      app.todos.each(this.filterOne, this); 
     }, 

     // Generate the attributes for a new Todo item. 
     newAttributes: function() { 
      return { 
       title: this.$input.val().trim(), 
       order: app.todos.nextOrder(), 
       completed: false 
      }; 
     }, 

     // If you hit return in the main input field, create new **Todo** model, 
     // persisting it to *localStorage*. 
     createOnEnter: function (e) { 
      if (e.which !== ENTER_KEY || !this.$input.val().trim()) { 
       return; 
      } 

      app.todos.create(this.newAttributes()); 
      this.$input.val(''); 
     }, 

     // Clear all completed todo items, destroying their models. 
     clearCompleted: function() { 
      _.invoke(app.todos.completed(), 'destroy'); 
      return false; 
     }, 

     toggleAllComplete: function() { 
      var completed = this.allCheckbox.checked; 

      app.todos.each(function (todo) { 
       todo.save({ 
        'completed': completed 
       }); 
      }); 
     } 
    }); 
})(jQuery); 

답변

1

잘못 컴파일 된 호건 템플릿을 사용하고 있습니다.

Hogan.compile()의 결과는 함수가 아니라 객체입니다. 그래서 "... 템플릿은 함수가 아닙니다"오류가 발생합니다. 컴파일 된 Hogan 템플릿을 렌더링하려면 객체의 "렌더링"기능을 호출해야합니다.

그래서 귀하의 경우, 당신은 더 많은 정보를

this.template.render(this.model.toJSON()) 

대신 방문 http://twitter.github.io/hogan.js

this.template(this.model.toJSON()) 

의 사용해야합니다.

관련 문제