2011-12-27 19 views
1

バックボーンで混乱させるtodoサンプルアプリケーションを作成しようとしています。私は、タスクのチェックボックスのクリックイベントがなぜ発火していないのか理解できません。ここでTaskCollection、TaskView、およびTaskListViewのための私のコードは次のとおりです。タスクのViewイベントは作成された要素で発生しませんか?

$(document).ready(function() { 

Task = Backbone.Model.extend({}); 

TaskCollection = Backbone.Collection.extend({ 
    model: 'Task' 
}); 

TaskView = Backbone.View.extend({ 
    tagName: "li", 
    className: "task", 
    template: $("#task-template").html(), 
    initialize: function(options) { 
     if(options.model) { 
      this.model = options.model 
     } 
     this.model.bind('change',this.render,this); 
     this.render(); 
    }, 
    events: { 
      "click .task-complete" : "toggleComplete" 
    }, 
    render: function(){ 
     model_data = this.model.toJSON(); 
     return $(_.template(this.template, model_data)); 
    }, 
    toggleComplete: function() { 
     //not calling this function 
     console.log("toggling task completeness"); 
    } 
}); 

TaskListView = Backbone.View.extend({ 
    el: $("#task-list"), 
    task_views: [], 
    initialize: function(options) { 
     task_collection.bind('add',this.addTask,this); 
    }, 
    addTask: function(task){ 
     task_li = new TaskView({'model' : task}); 
     this.el.append(task_li.render()); 
     this.task_views.push(task_li); 
    }, 
}); 
}); 

テンプレート:

<script type='text/template' id='task-template'> 
    <li class="task"> 
     <input type='checkbox' title='mark complete' class='task-check' /> 
     <span class='task-name'><%= name %></span> 
     </li> 
</script> 

私はtoggleCompleteイベントは、タスクのために発生しません理由を把握することができないよう。どうすればこの問題を解決できますか?

+0

私の答えはあなたのために働くのか、それとも明確ではないのですか? – Wieczo

答えて

2

問題は、新しいビューを作成するときに、バックボーンイベントは専用ビュー(this.el)の要素に設定することです。しかし、あなたの場合、要素は使用されません。したがって、ビュー内にtagName:li属性があります。これにより、バックボーンで新しいli要素が作成されますが、その要素は使用されません。返すのはテンプレートから作成された新しいリスト要素ですが、要素バックボーンは作成していません。アクセスできるのはthis.el

jQueryを使用してテンプレートで作成した要素に手動でイベントを追加するか、あなたの要素のinnerHTMLプロパティとしてテンプレート:

render: function(){ 
    model_data = this.model.toJSON(); 
    this.el = $(_.template(this.template, model_data)); 
    this.delegateEvents(); 
    return this.el; 
}, 

は、あなたが本当に李が含まれていないためにあなたのテンプレートを変更したほうが良いだろうと:

(this.el.html($(_.template(this.template, model_data))) 
0

.live()を使用するように.bind()を使用してリスナーを設定する行を変更してください。重要な違いは、ページロード後に作成される要素にリスナーをバインドする場合に、.live()を使用する必要があることです。

jQueryの最新バージョンは、この醜さを排除し、イベントリスナーを設定するためのメソッドを単純化します。

+0

バックボーンはフードの下で実際に 'delegate'を使用しています – blockhead

0

あなたのイベントが.task-completeのクラスに結合されていますが、チェックボックスのクラスがここに.task-check

+0

それを変更しました(そして私の質問を更新しました)、問題は解決しません。 – GSto

0

ので、同じようdelegateEvents()を呼び出すために、あなたのレンダリング機能を変更してくださいその後に戻りますthis.elを置き換えるのではなく、イベントを動作させたい場合はthis.elをルート要素にする必要があります。 delegateEvents()はイベントの内容を再接続するため、this.elを変更すると問題を解決するはずです。

0

@ AndreasKöberleが正しく回答します。イベントを動作させるには、何かをthis.elに割り当てる必要があります。

テンプレートとTaskView#render()機能が変更されました。 JSFiddleに変更が適用されています。それはrender()戻り、このことをお勧めし

render: function(){ 
    var model_data = this.model.toJSON(); 
    var rendered_data = _.template(this.template, model_data); 
    $(this.el).html(rendered_data); 
    return this; 
} 

新機能をレンダリングします。

TaskListView#addTask関数の1行がthis.el.append(task_li.render());からthis.el.append(task_li.render().el);に変更されます。

テンプレートの変更

我々はレンダリング()関数でthis.elを使用しているので、我々はテンプレートから<li>タグを削除する必要があります。

<script type='text/template' id='task-template'> 
    <input type='checkbox' title='mark complete' class='task-complete' /> 
    <span class='task-name'><%= name %></span> 
</script> 
関連する問題