Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
NabiZamani
Contributor
I started to answer the question of mike.doyle4, but then I realized my answer became a little too long. So I decided to write this little blog instead.

As Mike mentioned, this issue is not new (follow my code below or read Mike's question). I've had this issue quite often in UI5 projects, and the workarounds are just workarounds which I would prefer to avoid, i.e.

  • doing it the way Mike does it (if it's possible)

  • working with setTimeout (if possible, may need additional boilerplate code)

  • switching to liveChange if possible (may need additional boilerplate code)

  • moving all the code from event handlers into onPress of button if possible (may need additional boilerplate code)

  • executing only code in the change handle which does not block the press event (i.e. avoid alert(), avoid certain other operations changing the DOM)

  • ...


I can't give a rule of thumb because ​I've used different approaches based on the given scenarios.

See the following native HTML5/JS examples (or ​this jsbin for live demos), which I have tested on Safari 12.1.2, Chrome 76, Firefox 68.0.2, IE 11:

 

1. Works as expected: two events are always fired in correct order


<input onchange="console.log('onchange')">
<button type="button" onclick="console.log('onclick');">Click me</button>

This is what we expect in general - when changing the value of the input field and clicking the button we want to see the "onchange" before "onclick" in the console output. This works just fine.

 

2. Works as expected: two events are always fired in correct order


<input onchange="console.log('onchange');this.nextElementSibling.style.color='green';">
<div>Make me green in 'onChange'</div>
<button type="button" onclick="console.log('onclick');">Click me</button>

Even this works just fine in all browsers I've tested. First, we see "onchange" in the console, then the color of the text is changed to green via CSS, and finally we see "onclick" in the console. So even this small DOM change (the CSS change) is not causing any issues.

 

3. Attention: only onchange is fired on very first click (all browsers)


<input onchange="console.log('onchange');this.nextElementSibling.style.display='none';">
<div>Hide me in 'onChange'</div>
<button type="button" onclick="console.log('onclick');">Click me</button>

So let's do another DOM change, but this time some change which is slightly "bigger" - something that hides a DOM element. Interestingly, in this case only "onchange" will be printed in your console the first time consistently across all browsers. When you change the input field's value again and press the button again afterwards, the everything works as expected (because the <div> is already hidded).

 

4. Attention: only onchange is fired in Chrome/IE11/Safari


<input onchange="console.log('onchange');alert('onchange')">
<div>Show alert() in 'onChange'</div>
<button type="button" onclick="console.log('onclick');">Click me</button>

When using an alert() in onchange it gets weird. While Firefox shows "onclick" in the console after the alert() is closed by the user, the other browsers for some reason swallow the "onclick" event (meaning onclick is not triggered). The reason may be that onchange is triggered when the focus of the input field is lost, and when the dialog is opened and the user presses "ok" there can't be an onclick on the button (there's not even a focus on the button) - I guess this is why Chome/IE11/Safari behave like that. However, I kinda prefer the Firefox behavior here, it feels more natural to me.

Hint: alerts are considered evil theses days by the way.

 

5. Attention: onchange is fired AFTER onmousedown (all browsers)


<input onchange="console.log('onchange');alert('onchange')">
<div>Show alert() in 'onChange'</div>
<button type="button" onmousedown="console.log('onmousedown');">Mouse Down</button>

Ok, then maybe we could use ommousedown here. Well, we could, and in fact it works in all browser I've tested. However, the change event of the input field is fired after the mousedown event of the button. So now the order of the events is a little different. This is something I have to be aware of.

 

6. Attention: only onchange is fired, onmouseup is not fired at all in Chrome/Safari


<input onchange="console.log('onchange');alert('onchange')">
<div>Show alert() in 'onChange'</div>
<button type="button" onmouseup="console.log('onmouseup');">Mouse Up</button>

Well, then let's try onmouseup. Interestingly, onmouseup fires as expected and in the right order in Firefox and IE11. However, both Chrome and Safari don't fire onmouseup at all. IMHO, this feels strange.

You could also play around with oninput, I leave this as a task for you...

 

7. Conclusion


Well, this doesn't make life easier (as a JavaScript/WebDeveloper in general):

  • we have different browsers behaving deifferently

  • this is not a bug in UI5 itself, it's more about the browser's implementation

  • this issue is not even new, it's been around for mayn years

  • not sure why browser vendors aren't trying to tackle that flaw


All you can do is

  • making sure to test your code on different browsers

  • create awareness by telling other (ui5) developers

  • if possible, try to avoid code in onchange which changes the DOM (and I confess I can't avoid it myself in too many cases. In such cases good luck. 🙂

  • find some workaround based on your specific case


 

I know this is not a good conclusion. I'd be happy to hear a better conclusion from anyone else. This blog is more for creating some awareness.
1 Comment
Labels in this area