2016-10-24 1 views
0

Я использую мастер-представление с подвью с его собственным подзапросом, и я теряю событие на суб-под-представлении.Неподходящее событие backbone subview, доступ к this.model lost

Глядя на то, что это похоже на делегат, необходимо, но я не могу понять, как и где.

Кроме того, мне кажется, что действительно нужно принять tbody: tbodyEl[ "0" ].outerHTML в мой шаблон, но я не знаю, связано ли это с событием.

Любая помощь очень ценится.

MainView:

return Backbone.View.extend({ 
    el: "#content", 
    initialize: function() { 
     this.render(); 
    }, 
    render: function() { 
     var todosView = new TodosView({ 
      collection: projectCol 
     }); 
    } 
}); 

todosView:

return Backbone.View.extend({ 
    el: "#content-body", 
    template: _.template([ 
     '<div class="table-responsive">', 
     '<table id="todo-table" class="table">', 
     '<span class="caption">Top <%= project %> Tasks&nbsp;&nbsp;<a id="<%= project %>" class="projectName">(See All)</span></a>', 
     '<thead>', 
     '<tr>', 
     '<th>Task</th>', 
     '<th>Due</th>', 
     '</tr>', 
     '</thead>', 
     '<%= tbody %>', 
     '</table>', 
     '</div>' 
    ].join("")), 
    initialize: function() { 
     this.render(); 
    }, 
    render: function() { 
     var projectName = this.collection.models[0].attributes.project; 

     var tbodyEl = $("<tbody />"); 
     this.collection.each(function (item) { 
      var todoView = new TodoView({ 
       model: item 
      }); 
      tbodyEl.append(todoView.el); 
     }); 
     this.$el.append(this.template({ 
      project: projectName, 
      tbody: tbodyEl["0"].outerHTML 
     })); 
    } 
}); 

todoView:

return Backbone.View.extend({ 
    tagName: "tr", 
    className: "todo-rec", 
    template: _.template([ 
     "<td>", 
     "<label id='task' class='edit'><%= task %></label>", 
     "<input id='edited-task' class='new-edit' style='display:none;' value='<%= task %>'>", 
     "</td>", 
     "<td>", 
     "<span id='due' class='edit'><%= due %></span>", 
     "<input id='edited-due' class='new-edit' style='display:none;' value='<%= due %>'>", 
     "</td>", 
    ].join("")), 
    events: { 
     "click .edit": "editFields" 
    }, 
    initialize: function() { 
     this.render(); 
    }, 
    render: function() { 
     this.$el.html(this.template(this.model.toJSON())); 
     return this; 
    }, 
    editFields: function() { 
     console.log("todoView: editFields clicked"); // <-- does not fire 
    } 
}); 

25 октябрем Обновлено: Благодаря @WinterSoldier, это то, что я закончил с: Код сборки элементы заполнены перед вставкой в ​​DOM, а todoView.events работает, давая полный доступ к this.model, плюс, он loo кс более «Магистраль-иш»:

// mainView: 
return Backbone.View.extend({ 

    el:    "#content", 

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

    render:   function(){ 
        $("#content-body").empty(); 

        var section = new TodosView({ collection: projectCol }); // should be returning a section div 
        $("#content-body").append(section.el); 
       }       
}); 


// todosView: 
return Backbone.View.extend({ 

    // used tagName so the element can be built complete before inserting into DOM 
    tagName:  "div", 
    className:  "table-responsive", 

    // tbody changed to empty element 
    template:  _.template([ 
        '<table id="todo-table" class="table">', 
         '<span class="caption">Top <%= project %> Tasks&nbsp;&nbsp;<a id="<%= project %>" class="projectName">(See All)</span></a>', 
         '<thead>', 
          '<tr>', 
           '<th>Comp.</th>', 
           '<th>Task</th>', 
           '<th>Due</th>', 
           '<th>Priority</th>', 
           '<th>Delegated To</th>', 
           '<th>Project</th>', 
           '<th>Del.</th>', 
          '</tr>', 
         '</thead>', 
         '<tbody id="tbodyContent"></tbody>', 
        '</table>' ].join("") 
       ), 

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

    render:   function(){ 
        // new: render the template first, then append rows in #tbody 
        var projectName = this.collection.models[ 0 ].attributes.project; 
        this.$el.empty().html(this.template({ 
         project: projectName 
        })); 

        var this2 = this; 
        this.collection.each(function(item){ 
         var todoView = new TodoView({model: item}); 
         this2.$el.find("#tbodyContent").append(todoView.el); 
        }); 
        // now returning a <div class="table-responsive" with all rows 
        return this; 
       } 
    }); 



// todoView: 
// Note: nothing changed from original code 

return Backbone.View.extend({ 

    tagName:  "tr", 
    className:  "todo-rec", 

    template:  _.template([ 
         "<td>", 
          "<label id='task' class='edit'><%= task %></label>", 
          "<input id='edited-task' class='new-edit' style='display:none;' value='<%= task %>'>", 
         "</td>", 
         "<td>", 
          "<span id='due' class='edit'><%= due %></span>", 
          "<input id='edited-due' class='new-edit' style='display:none;' value='<%= due %>'>", 
         "</td>", 
        ].join("") 
       ), 

    events:   { 
        "click .edit":  "editFields" 
       }, 

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

    render:   function() { 
        this.$el.html(this.template(this.model.toJSON())); 
        return this; 
       }, 


    editFields:   function() { 
        console.log("todoView: editFields clicked", this); 
       } 

    }); 

ответ

-1

позвольте мне перечислить предположения, я сделал на основе вопроса:

  • Рендеринг шаблон не имеет никаких проблем.
  • Код шаблона может быть заменен простым html, чтобы проверить стрельбу .

Основываясь на этих предположениях, я создал коллекцию с двумя моделями и передал их в TodosView, из которого я повторил эти модели для создания представления строк, добавив его в тег tbody.

Пожалуйста, следуйте скрипку здесь => https://jsfiddle.net/randomfifaguy/304kffed/1/

console.log("hello"); 
 
Test = Backbone.Model.extend({}); 
 
var testModel1 = new Test({ 
 
    'task': 'taskA', 
 
    'due': 'dueByZ' 
 
}) 
 
var testModel2 = new Test({ 
 
    'task': 'taskB', 
 
    'due': 'dueByY' 
 
}) 
 
console.log(testModel1.get('task')); 
 
console.log(testModel2.get('task')); 
 
ModelCollection = Backbone.Collection.extend({}); 
 
var models = new ModelCollection([testModel1, testModel2]); 
 
console.log(models); 
 

 
TodosView = Backbone.View.extend({ 
 
    el: "#content-body", 
 
    initialize: function() { 
 
     this.render(); 
 
    }, 
 
    render: function() {  
 
    var templ = "<div class='table-responsive'><table id='todo-table'class='table'><span class='caption'>Top Tasks&nbsp;&nbsp;<a id='<%= project %>' class='projectName'>(See All)</span></a><thead><tr><th>Task</th><th>Due</th></tr></thead><tbody></tbody></table></div>"; 
 
    $(this.el).html(templ); 
 
    _.each(this.collection.models, function(mdl){ 
 
    \t var view = new TodoView({ 
 
     model: mdl 
 
    });  
 
    $('tbody').append(view.el); 
 
    });  
 
    } 
 
}); 
 

 
MainView = Backbone.View.extend({ 
 

 
    el: "#content", 
 

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

 
    render: function() { 
 
     new TodosView({ 
 
     collection: models 
 
     }); 
 
    } 
 
}); 
 

 
TodoView = Backbone.View.extend({ 
 
    tagName: "tr", 
 
    className: "todo-rec", 
 
    events: { 
 
     "click .edit": "editFields" 
 
    }, 
 
    initialize: function() { 
 
     this.render(); 
 
     this.updateContent(); 
 
    }, 
 
    render: function() { 
 
    var html = "<td><label id='task'class='edit tasklabel'></label><input id='edited-task'class='new-edit taskinput'style='display:none;' value=''></td><td><span id='due' class='edit duelabel'></span><input id='edited-due' class='new-edit dueinput' style='display:none;'value=''></td>" 
 
    this.$el.html(html); 
 
    return this; 
 
    }, 
 
    editFields: function() { 
 
     console.log("todoView: editFields clicked"); 
 
    }, 
 
    updateContent: function() { 
 
     this.$el.find('.tasklabel').text(this.model.get('task')) 
 
     this.$el.find('.taskinput').val(this.model.get('task')) 
 
     this.$el.find('.duelabel').text(this.model.get('due')) 
 
     this.$el.find('.dueinput').val(this.model.get('due')) 
 
    } 
 
}); 
 

 
var mainViewObj = new MainView();
<body> 
 
    <div id='content'> 
 
     Here is a sample div 
 
     <div id="content-body"> 
 
     content to be changed 
 
     </div> 
 
    </div> 
 
</body>

Однако я хотел бы знать ваши HTML от внешней точки зрения, чтобы помочь вам лучше. Пожалуйста, сравните его с выходом html скрипки и дайте мне знать. Надеюсь, что ответит на ваш вопрос.

Ответ на ваш комментарий подробно Вы можете изменить этот кусок кода

//You might want to change this piece of code 
 

 
    var tbodyEl = $("<tbody />"); 
 
    this.collection.each(function (item) { 
 
     var todoView = new TodoView({ 
 
      model: item 
 
     }); 
 
     tbodyEl.append(todoView.el); 
 
    }); 
 
    this.$el.append(this.template({ 
 
      project: projectName, 
 
      tbody: tbodyEl["0"].outerHTML 
 
    }));

Ваш tbodyEl в основном указывает на нет, пока вы не воздавал попытаться сделать это, прежде чем добавить в TBODY

this.$el.append(this.template({ 
 
     project: projectName, 
 
     tbody: tbodyEl["0"].outerHTML 
 
    })); 
 
    // followed by 
 

 
    this.collection.each(function (item) { 
 
     var todoView = new TodoView({ 
 
       model: item 
 
      }); 
 
      tbodyEl.append(todoView.el); 
 
    });

+0

Спасибо, это работает, я получаю доступ к this.model onclick, но я до сих пор не понимаю, почему в TodosView использование шаблона Backbone и объекта JQuery tbody не работает. Из чтения SO, кажется, я теряю функцию «делегата» где-то. Кроме того, я надеялся избежать обновления DOM с каждым значением. Мысли? – royhink

+0

вы пытаетесь получить доступ к tbody в todosView еще до его рендеринга. –

 Смежные вопросы

  • Нет связанных вопросов^_^