1

I have a <select> form element that is being generated dynamically after the page loads. I was using jQuery to attach a change event that would update other fields in the form, and wanted to eliminate the need to rewire the handler each time the form containing the <select> was replaced.

For click events on dynamic elements, I have been moving to unobtrusive JavaScript and wanted to use that approach for change - but no success. Attaching to the <select>directly was cumbersome because when the node is replaced in the DOM, the connected event listener dies with it, and the new node must be attached to again.

So I wanted to know, is there a way to unobtrusively assign a change event handler to the parent element of a newly-created <select> and let the event bubble up to a handler on a previously-existing element, in order to avoid attaching a handler each time a new target input element is created?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
brichins
  • 3,825
  • 2
  • 39
  • 60
  • @AlexanderO'Mara I _knew_ there had to be questions that addressed this, but couldn't find anything useful with the tags I was searching. Of course you would find one over 6 years old within minutes :) Just one of those no-brain days for me - I think it's time to put away the keyboard and go do something else for a while. – brichins Nov 04 '15 at 01:12
  • Duplicate flag accepted. Hopefully someone thinking in the same keywords I was can pass from here to the previous question. – brichins Nov 04 '15 at 01:15
  • 1
    Not the same as the linked question, as explained in the answer below: the linked answer concerns click, mouseover, mouseout, which exist on all elements, but inputs are a special case where the suggested solution does not apply. – nvioli Feb 24 '17 at 22:14

1 Answers1

0

Yes!

$('#StaticParentNode').on('change',"select.qualifiers", function(){ alert("Change detected from parent"); });

Naturally, I finally got this working 2 minutes after posting my original answer (below). Doh.


No.

While attaching unobtrusive event listeners on a parent <div> or the document works great for bubbling click events from elements that didn't previously exist on the page, you can only attach an event listener to an element that has that type of event.

As stated in the jQuery .change API docs (although this issue is not jQuery specific):

The change event is sent to an element when its value changes. This event is limited to <input> elements, <textarea> boxes and <select> elements.`

Since <div> and document do not have a change event, they cannot intercept one from their children either.

Solutions:

  1. Just set onchange to a previously-defined function when you generate the element: <select onchange='MyModule.selectChanged()'>[<options>]</select>. Not pure from a separation of concerns standpoint, but a simple approach with minimal extra HTML added to an AJAX request, and no fiddling with handlers after the AJAX call completes.

    or,

  2. (Re)attach an event listener each time you create new elements that require it, either 'manually' (e.g. in a $.ajax success function) or by wiring it into whatever tool is handling your AJAX results (e.g. modifying or extending .prototype). See examples elsewhere on SO.

brichins
  • 3,825
  • 2
  • 39
  • 60