Reputation: 1717
I'm attempting to write some Javascript objects to manage dynamic forms on a page.
The forms object stores an array for forms and renders them into a container.
I'd like to have click events for certain fields on each form so decided to make a seperate object and tried to bind an event inside the objects init
method.
The init method is clearly fired for every new form that I add. However on change event only ever fires for the last form object in my array.
JS Fiddle Demonstrating Issue
can be found: here
function Form(node) {
this.node = node;
this.init = function() {
$(this.node).find("input:checkbox").change(event => {
console.log('Event fired');
});
};
this.init();
}
// Object to manage addition / removal
var forms = {
init: function() {
this.formsArray = [];
this.cacheDom();
this.bindEvents();
this.render();
}
// Only selector elems from the DOM once on init
cacheDom: function() { ... },
// Set up add / remove buttons to fire events
bindEvents: function() { ... },
render: function() {
for (let form of forms)
this.$formSetContainer.append(form.node)
}
addForm: function() {
// Logic to create newRow var
this.formsArray.push(new Form(newRow));
},
removeForm: function() {
// Logic to check if a form can be removed
this.formsArray.pop();
}
},
What I've Tried Already
I'm actually able to bind events inside render
by removing this.init()
inside the Form constructor and altering render
like so:
for (let form of this.formsArray) {
this.$formSetContainer.append(form.node)
form.init();
}
Then the events will successfully fire for every form
But I'd rather not have this code run every time I call render()
which is called every time I add / remove forms.
I have a feeling that this is a scoping issue or that the event is somehow being clobbered. Either that or I'm misunderstanding how events are bound. Any pointers would be appreciated
Upvotes: 2
Views: 1006
Reputation: 324
Looking at the code in the JSFiddle, the problem comes from using this.$formSetContainer.empty()
in the render function. .empty() removes all the event handlers from your DOM nodes.
To avoid memory leaks, jQuery removes other constructs such as data and event handlers from the child elements before removing the elements themselves.
If you want to remove elements without destroying their data or event handlers (so they can be re-added later), use .detach() instead.
You can replace this with this.$formsetContainer.children().detach()
and it will do what you want.
Upvotes: 1