Technical Articles relating to Oracle Development Tools and Frameworks

  • JET
    July 28, 2017

JQuery Style Selectors Inside of Composite Components

Duncan Mills

I hit a bug in one of my composite components the other day which I thought I'd share with you all as I feel that it's a trap that it's all too easy to fall into.

The problem in question relates to the attachment of an keyPress listener on an input field within the component.  The basic functionality I was putting in place was simply to navigate to the next field in sequence if the user pressed the "." key.  Simple enough....

The Initial Solution  

As I had several input fields that would need the same handler I decided that the simplest approach would be to use a JQuery selector based on a style class to apply listeners to each of the applicable fields rather than iterating through each one in turn. 

$('.svi-segment').keypress(function (event) {...}

This worked perfectly - job done, or so I thought. 

Problem and Resolution

Fast forward a few days, and I was testing the component in a situation where several instances where on the same page. It was then that I realized my mistake.  The CSS class I was using was of course unique to the composite component, so when used in the context of just one instance of the component on the page, its use as a selector worked as expected and just those fields that needed it had the handler attached. However, of course, when you have multiple instances of your component on the page, that component-private style-class is now common across all instances of the component.  The result of this is, that each input with the associated "svi-segment" class was getting a listener from every component instance on the page, i.e. the component that it was actually a part of and all the others as well. As you can imagine, the resulting behaviour was sub-optimal!

The good news is that this is simple to fix once you are aware of it as an issue, you can use an decendent selector in combination with the class to narrow down the targets to the context of the actual component instance.  In my case this was just a tiny change to the code:

  //self.composite is a stored reference to the component element passed in via the context
  $('#'+ self.component.id + '.svi-segment').keypress(function (event) {...}

The lesson here is simply to exercise a little caution when using JQuery selectors within a composite component, and even if you think that there will only ever be one copy on the page at once. Code defensively, just in case.

Oh and before anyone mentions it, of course you can do all this without using JQuery to select the elements. The getElementsByClassName() API will do the trick, although again you need to start searching from the composite element as the root, rather than document, otherwise you'll end up with the same problem!

Join the discussion

Comments ( 2 )
  • Nikhil Sunday, September 24, 2017
    I have been using the following approach for the issue. Seems to work fine till now .

    $('.svi-segment',self.component ).keypress(function (event) {...}

    Do you find anything wrong with this approach ?
  • Duncan Monday, September 25, 2017
    Sure that's fine because you are consciously restricting the selector to the Union of those two criteria. The key is that any JQuery selector pattern that you use should be specific enough to handle multiple instances on the page, both as peers and *children* of the component you're defining the listener for.
Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.