Jack Evans
Jack Evans

Reputation: 1717

Jquery binding event to object on initialization only works for single object

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

Answers (1)

Matt
Matt

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.

https://api.jquery.com/empty/

You can replace this with this.$formsetContainer.children().detach() and it will do what you want.

Upvotes: 1

Related Questions