1

Currently I have html like this:

<div class="selector-wrapper">
    <label for="product-select-1372104458328-option-0">Style</label><select class="single-option-selector" data-option="option1" id="product-select-1372104458328-option-0">
        <option value="Adjustable">
            Adjustable
        </option>
        <option value="Flex Fit">
            Flex Fit
        </option>
        <option value="Trucker Hat">
            Trucker Hat
        </option>
    </select>
</div>

my jquery code is this:

$(function() {
    $('.single-option-selector').on('change', function() {
    console.log( 'blahblah' );
    });
});

the expected result would be for there to be a console.log when the option changes in .single-option-selector however that is not the case I get nothing. No error or anything. Any ideas what I'm doing wrong?

5
  • Doesn't look like there is a problem here: jsfiddle.net/teddyrised/0fnaq1bx. Are you using any kind of plugin that might be replacing the <select> element? Commented Jan 8, 2019 at 1:04
  • It's part of a shopping cart, shopify but after all loads I'm able to view the html I placed above. There are however several single0option-selectors on the page would that have anything to do with it? @Terry Commented Jan 8, 2019 at 1:07
  • 1
    It shouldn't be a problem, since jQuery will bind the handler iteratively to all nodes that matches the selector. I'm guessing that the element is somehow not available at runtime, so the handler is never bound. Have you tried $(document).on('change', '.single-option-selector', function () {...});? Commented Jan 8, 2019 at 1:09
  • worked! why would that work and not other? @Terry Commented Jan 8, 2019 at 1:13
  • The suggested alternative works because it listens to event bubbling up to document. Since document is always present at runtime, we will always be able to catch the onchange event bubbling up. However, using $(document) incurs a performance overhead: I'll detail that in a followup answer. Commented Jan 8, 2019 at 1:17

1 Answer 1

2

As you have mentioned that the markup is generated by Shopify, it is very likely that the <select> element you are choosing is actually unavailable at runtime (i.e. it has not been injected in the DOM yet). In this case, jQuery fails silently when it cannot find the element to bind event handlers to. You can run a simple check by plugging this line in:

console.log($('.single-option-selector').length);

My suspicions are confirmed if it returns 0, which means at runtime your script cannot find the relevant element in your DOM. The way to overcome this is by using event bubbling: basically you attach an event handler to a pre-existing element at runtime, and simply filter the event so that you only catch those emitted by elements identified with your selector, i.e.:

$(document).on('change', '.single-option-selector', function () {
    // Your logic here
});

However, this approach has a drawback: there is a significant overhead by listening to events on the top level document. If you know that there is an element that is always available at runtime, let's say the given DOM structure:

<body>
    <!-- This element is always present at runtime -->
    <section id="content">
        <!-- Contains dynamically injected HTML -->
    </section>
</body>

Then you can update your selector to listen to events bubbling up to #content and not further up:

$('#content').on('change', '.single-option-selector', function () {
    // Your logic here
});
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.