0

I am currently working on a Table Editor in Javascript and in my code I have the following setup which attempts to add a listener, after the HTML has been generated and appended to the table (a single row):

$(self.tableName + ' tbody').append(htmlString);
$(self.tableName + ' tbody tr').each(function (outerIndex) {
    let id = $(this).find('td')[0].innerText;
    if (id === elements[0]) {
        $(this).find(':input').each(function (inputIndex) {
            $(this).change(function (e) {
                self.OnFieldValueChanged(objectCollection, elements[0], (inputIndex + 1), $(this).val());
            });
            if (self.options !== undefined) {
                if (self.options.eventListeners !== undefined && self.options.eventListeners[inputIndex] !== undefined) {
                    let eventListenerArrLength = self.options.eventListeners[inputIndex].length;
                    for (let eventIndex = 0; eventIndex < eventListenerArrLength; eventIndex++) {
                        let event = self.options.eventListeners[inputIndex][eventIndex].event;
                        $(this).on(event, (e) => { self.options.eventListeners[inputIndex][eventIndex].listenerFunction(e) });
                    }
                }
            }
        });
    }
});

Now the weird thing is, this line here

$(this).change(function (e) {
    self.OnFieldValueChanged(objectCollection, elements[0], (inputIndex + 1), $(this).val());
});

Actually works as intended. When a value changes in the table, this makes sure that my object representation of the table updates accordingly. However, this piece of the code:

if (self.options !== undefined) {
    if (self.options.eventListeners !== undefined && self.options.eventListeners[inputIndex] !== undefined) {
        let eventListenerArrLength = self.options.eventListeners[inputIndex].length;
        for (let eventIndex = 0; eventIndex < eventListenerArrLength; eventIndex++) {
            let event = self.options.eventListeners[inputIndex][eventIndex].event;
            $(this).on(event, (e) => { self.options.eventListeners[inputIndex][eventIndex].listenerFunction(e) });
        }
    }
}

Does not do as intended. While the code does run it doesn't do as I want it to. The idea here is that given an options object, certain columns may have event listeners attached to do who knows what. My current function that I refer to here (self.options.eventListeners[inputIndex][eventIndex].listenerFunction(e)) is a function designed to only allow certain characters in a field and ignore everything else. So I use the 'keydown' event to achieve this.

But, alas, after the table has made the row and input elements that this code is attached to, the keydown event never triggers the function I added with $(this).on(...).

The let event = self.options.eventListeners[inputIndex][eventIndex].event; is literally just a string taken from an enum like const I've made. It currently holds either "change" or "keydown". So that should be good.

What am I missing about this setup?

OmniOwl
  • 4,893
  • 14
  • 52
  • 99
  • 1
    Looks like you're trying to re-invent the wheel. Just use event delegation: `$(self.tableName).on("change", "tbody tr :input", function() { /* always fires */ });` (or `$(document).on("change", self.tableName + " tbody tr : input", function() ..` if you prefer. – freedomn-m Jan 14 '20 at 10:04
  • I need to make sure this is only bound to certain input fields as I will have many tables on the same page and those input fields may have different formatters/event listeners depending. – OmniOwl Jan 14 '20 at 10:06
  • 1
    You can achieve that by providing information on the input via `data-` attributes. – freedomn-m Jan 14 '20 at 10:07
  • 1
    Essentially: if what you're trying doesn't work (and it appears overly complicated to me at first glance), don't spend ages trying to get it to work when there are other (*potentially*) simpler methods. – freedomn-m Jan 14 '20 at 10:08
  • @freedomn-m That is easy to say, if you know of those other methods. I have tried many methods so far to make this work, including deprecated `bind()`, `change(...)/keydown(...)` and even `$(this).onkeydown = func...`. It isn't from lack of trying. – OmniOwl Jan 14 '20 at 10:09
  • 1
    No, you misunderstand, I'm not trying to belittle what you've done - apologies if it came across that way. Have a read about event delegation: https://stackoverflow.com/questions/203198/event-binding-on-dynamically-created-elements – freedomn-m Jan 14 '20 at 10:10
  • I am not checking for existing events. The `self.options` object is something that may or may not be passed in when the Table Editor is created. So this means that I have to check if the object itself exists, and if that object holds any event listeners that should be applied to the input field. – OmniOwl Jan 14 '20 at 10:11
  • @freedomn-m okay, this makes no sense to me. I just put a debug point in my code where the code is for the keydown function. When I press 'a' in a field I'm not supposed to, the breakpoint triggers, I step through my code and it doesn't allow me to type 'a' just as its supposed to. But as soon as I remove the breakpoint, the code stops working as intended again ._. – OmniOwl Jan 14 '20 at 10:31
  • Try changing `$(this).on(event, (e) => { self.options...` to `$(this).on(event, (e) => { return self.options...` – freedomn-m Jan 14 '20 at 12:51
  • @freedomn-m I was so close to having that solution...thanks! – OmniOwl Jan 14 '20 at 12:56

0 Answers0