Event binding is a common pattern in JS, and here is one way to do it from a code I read: $('#toggle-all').on('change', this.toggleAll.bind(this));
In this case, there is an input with id toggle-all, which runs the this.toggleAll
method when clicked.
However, even without binding, eg $('#toggle-all').on('change', this.toggleAll);
the toggleAll
method can still run, although it hits an error halfway through the method. But it still runs.
However, for another method: todoLi.appendChild(this.createDeleteButton());
this.createDeleteButton()
does not run at all if I do not bind it. What is the difference between the two examples? I know one is passing in a (callback) function as a parameter, and the other is directly running the method. But the second example does not run at all without binding while the this.toggleAll
method runs even without binding. Why is this so?
var App = {
bindEvents: function () {
$('#toggle-all').on('change', this.toggleAll); // without binding
},
toggleAll: function (e) {
console.log(this); // prints jQuery object which is the input #toggle-all
var isChecked = $(e.target).prop('checked');
// error from this line onward, which is expected.
this.todos.forEach(function (todo) { // "this" is the input element, hence error
todo.completed = isChecked;
});
this.render();
}
};
For the second option, here is the code:
var view = {
displayTodos: function() {
var todosUl = document.querySelector('ul');
todosUl.innerHTML = '';
todoList.todos.forEach(function(todo, position) {
var todoLi = document.createElement('li');
var todoTextWithCompletion = '';
if (todo.completed === true) {
todoTextWithCompletion = '(x) ' + todo.todoText;
} else {
todoTextWithCompletion = '( ) ' + todo.todoText;
}
todoLi.id = position;
todoLi.textContent = todoTextWithCompletion;
todoLi.appendChild(this.createDeleteButton());
todosUl.appendChild(todoLi);
}, this); // binding "this". If I remove it, the error I get in the console is: client.js:90 Uncaught TypeError: this.createDeleteButton is not a function
},
// creates a delete button beside every li element in the DOM.
createDeleteButton: function() {
console.log(this);
var deleteButton = document.createElement('button');
deleteButton.textContent = 'Delete';
deleteButton.className = 'deleteButton';
return deleteButton;
},
Main question: Why is it that a method can be run without binding (in the first case). But in the second case, it cannot be run at all without binding? AKA Why does jQuery.on() accept the un-binded this.toggleAll, but appendChild is not able to accept the un-binded this.createDeleteButton()?