2004.12.06 12:55 PM

IE: Changing a Textbox Value in its OnChange Event

If you programmatically change the value of a textbox (i.e., input type="text") while handling its onchange event, don't expect IE to recognize the new value the next time it evaluates a change to the textbox.

To see this for yourself, save the following to an HTML file and open it in IE (or just use this):

<html>
 
<head>
   
<script type="text/javascript">
      
function setValue(target) {
        alert(
"changed - value: " + target.value);
        target.value
+= target.value;
      }
   
</script>
 
</head>
 
<body>
   
<form>
      
<div>
        Enter "a" here:
       
<input type="text" id="test" onchange="setValue(this)"> 
       
<br/>
       
<br/>
       
<input type="text"> 
      
</div>
   
</form>
 
</body>
</html>

Type an "a" into the first textbox and press Tab. You'll see the onchange event's alert, and the textbox's value will appear to change to "aa". However, if you return to the textbox and type "a" again, replacing the "aa", and press Tab, the onchange event will not be raised and you will not see the alert. That's because IE thinks the control's value is still "a".

Here's another way to see the problem. Press F5 to refresh the page, then type "a" into the first textbox and press Tab. After the onchange alert, return to the first textbox, change nothing and press Tab again. You'll see the onchange event's alert, because IE finally noticed the change from "a" to "aa".

Fortunately, the solution is simple. Just disconnect the logic responsible for changing the control's value from the onchange event's execution path using a setTimeout. The following HTML works as expected (or just use this).

<html>
 
<head>
   
<script type="text/javascript">
      
function setValue(target) {
        alert(
"changed - value: " + target.value);
        setTimeout(
"reallySetValue('" + target.id + "');", 1);
      }
      
function reallySetValue(id) {
       
var control = document.getElementById(id);
        control.value
+= control.value;
      }
   
</script>
 
</head>
 
<body>
   
<form>
      
<div>
        Enter "a" here:
       
<input type="text" id="test" onchange="setValue(this)"> 
       
<br/>
       
<br/>
       
<input type="text"> 
      
</div>
   
</form>
 
</body>
</html>

Note that none of this is a problem for FireFox. It correctly recognizes value changes during onchange processing, and it doesn't have a problem with the IE workaround.

So, why would anyone change a control's value while handling its onchange event? Well, my browser-based forms often format manually entered values for better presentation. So, for instance, if a user enters "1234" into a monetary field, I often reformat it as "$1,234.00" when they exit the field. I do similar things with dates.

I looked to see whether Microsoft considers this a bug, but found only one semi-related Knowledge Base article (Q817979).


Comments

iuyi

| 2004.12.22 02:38 PM

I came across this while trying to figure out why IE seems to fire off the onchange event (for a set of radio buttons in my case) before it applies the change. This caused me problems because during the event handler, the selected radio button was the old selection, not the one it was changing too.

Is this a general issue for IE perhaps, in the way it handles onchange (by calling the event handler, then applying the change)? That would certainly explain your problem. The timeout solution works for my issue as well, although I found it to be a little flaky. And likewise, I also found that firefox behaved in the way I would expect.

Craig Ambrose | 2005.01.05 10:58 PM

Hi Craig,

Thanks for taking the time to comment.

While onchange events for radio input controls in FireFox work as expected (God bless 'em), they don't in IE (and never have, I think). In IE, the onchange event for radio control buttons isn't even fired for the first change, and (as you pointed out) subsequent onchange events always reflect the control you're leaving, not checking.

So instead of using the onchange event for radio input controls, I've always used the onclick event. It works as expected in both IE and FireFox.

Admittedly, I had never tried setting the checked property of a radio input control during execution of the onclick event for another radio input control in the same group. But, I just tried it and didn't experience the latent value setting problem I experienced with text input controls (as described above). The change was registered immediately (I could see the alternate radio input control get marked) and a quick loop over all the radio input controls in the group showed that the one I 'checked' programmatically during the onclick event was in fact the one currently thought by IE to be checked.

If you'd like an example of this, I'd be happy to share it in a new blog post.

Good luck!

ewbi.develops | 2005.01.06 12:50 AM

Your comment regarding IE's onchange event and radio buttons is incorrect. The HTML standard says that the onchange should fire when the control loses focus. When you click a radio button, it has focus so the onchange (in IE) doesn't fire. Clicking anywhere else in the document (including on another radio button) will cause IE's onchange to fire for the control losing focus, not the one gaining focus.
Firefox does not follow the standard - onchange fires when you click on the button, not after it has lost focus. Whilst Firefox is probably more logical (the control changed so the event occurs), it is equivalent to an onchange firing as soon as you type into a text input rather then when you have finished typing and 'tab' to the next field.
Whilst Firefox's implementation may seem better, it doesn't follow the standard whereas IE (for once) does. Using onclick is generally frowned upon because it infers a user action whereas onchange doesn't (a UA without a GUI can't click on the control). However, that is not my opinion and I believe non-GUI UAs will likely handle onclick OK anyway.

RobG | 2005.01.24 06:02 PM

RobG,

It never dawned on me that IE might group the radio input controls for the purpose of controlling the onchange event. In that light, the IE behavior does make more sense than FireFox.

Thanks for taking the time to explain!

ewbi.develops | 2005.01.24 07:52 PM

Thanks so much for the tip on using onclick instead of onchange for radio buttons. My script finally "works" in IE as well as Firefox!

Max Starkenburg | 2005.09.07 01:29 PM

We've been ignoring this problem for a long time, thinking there wasn't a good solution.

This is perfect, THANKS!

Nathan | 2006.04.13 10:48 AM

Nathan - glad to hear it!

ewbi.develops | 2006.04.14 05:14 PM

Thanks for that. I just changed my onChange= to onClick= and everything works for me now.

I was having problems with radio buttons and checkboxes in IE 6. The weird thing is I was expecting I'd have to do some tricky things with the elements to make sure they also triggered this event, but they just worked.

Kinda weird really! Anyone got an explanation?

Tarwin | 2006.06.27 09:28 PM

You're welcome, Tarwin. Hope someone wonders by and drops you an explanation. Don't hold your breath, though, traffic here is really light.

ewbi.develops | 2006.06.27 11:31 PM

Hi,

Is it possible to get the old value of a textbox on its onchange event. i.e., when I change the value in the text box onchange even gives only the new value, but I want to have the old value as well.

Aman | 2006.06.30 02:30 AM

Hi Aman,

I don't believe so. While IE still has (somewhere) a record of what it thinks the value was/is, as illustrated in the post above, it isn't accessible. And in FireFox, there's no sense of having an original vaue at all. You're best bet is to preserve the values yourself - send them to the browser in JavaScript dynamically generated by the server, or capture the original values in the onload event. I tend to use the former approach, then use JavaScript to distribute the values to the appropriate controls in the onload event. Then with each onchange event I can compare/evaluate the original and new values, perhaps setting a dirty flag. This also allows me to provide an undo/reset feature without a trip to the server.

Good luck.

ewbi.develops | 2006.06.30 10:28 AM

Hello, I found onChange event not to work in FF(1.5.0.4) either...


you must do it by manually editing in edit box, and event only burns when you exit the control (not while changing).

m227 | 2006.07.01 08:18 AM

Hi m227,

Unless I'm misunderstanding you, I believe that's the expected onchange behavior. The event is only raised by manual changes, not programmatic ones, and it is only thrown when the change is committed, which is as you leave the textbox. If you want to deal with changes in textboxes as they occur, take a look at the onkeydown and onkeypress events (there's also onbeforecut, onbeforepaste, oncut, onpaste, etc.).

Good luck.

ewbi.develops | 2006.07.01 11:57 AM

I found out that you can also cancel the event using, window.event.returnValue = false; and IE will handle the Change event correctly the next time.

Darin | 2006.07.10 12:06 PM

Thanks for adding that, Darin. Might come in handy.

ewbi.develops | 2006.07.10 12:19 PM

I am facing one problem.
I have a textbox on a form and this textbox readonly. I am setting value of this textbox programmatically. Now I need to capture this event and wants to call a function in javascript for setting other values on the form; tried with the onChange and onTextChange but not able to call javascript function.
Please, give me some way to implement this.

Thanks in advance.

Regards
Ambalal

Ambalal | 2006.07.27 12:13 AM

Hi Ambalal,

My response to your question was too long for a comment, so I wrote it up as a separate post:

http://ewbi.blogs.com/develops/2006/07/onchange_handle.html

ewbi.develops | 2006.07.27 10:25 PM

The poster who commented that IE is actually following the standard is correct; onchange only fires when the INPUT loses focus.

My solution was to keep the onchange as is, but to blur() the element upon clicking. So my final element looked like this:

[input type="checkbox" onclick="this.blur()" onchange="handleit(this)" /]

This allows IE to see the onchange event immediately. Note that solution really only makes sense for checkboxes and radio buttons.

Kenan Banks | 2006.08.09 08:15 AM

Kenan, thanks for the info.

ewbi.develops | 2006.08.09 09:55 AM

Thanks for the guide to onchange, I was having problems getting a hidden text form to call a function when the text inside changed. I've used the onchange method now and it's working fine,

Cheers

Al

Al Mack | 2006.08.20 11:49 AM

Thanks! about this script

Nguyen Van khoai | 2006.10.18 03:04 AM

Yeap, many thanks!

Thai Radio | 2007.01.19 11:59 PM

Hi, thanks for commenting to my own frustrated article... Glad to know there's a solution to this bug. But watch out for Opera, that beast was over-zealous and fired onchange twice with radio buttons (one when de-selecting the former, one when selecting the latter).

/rant mod on
How can such an age-old mechanism be so differently implemented across browsers? Radio inputs date back to the very first versions of HTML, dammit!
/rant mode off

Goulven | 2007.03.07 12:24 PM

Hi this article helped.. i didnt know that this was an issue with IE.
for me the soution was simple, i used onblur instead of onchange. it will execute the function even if there is no change, but i can live with that :)

Sandeep | 2007.05.16 02:56 AM

use the onMouseup event. It will record the change prior to firing the event.

Kai | 2007.06.08 12:20 AM

use the onMouseup event. It will record the change prior to firing the event.

Kai | 2007.06.08 12:20 AM

Thanks a lot Craig, it took me a few hrs to find this information, and 30 seconds to get it working. Thanks a million.

Martin Imhoff | 2007.06.08 11:44 AM

Nearly 3 years since first posted and this bit of advice regarding the onchange for inputs is still providing an elegant solution to a problem that is obviously not fixed (or not recognized as a bug) in IE in 3 years.

Thanks

Gary | 2007.09.07 08:48 AM

Thank you very much for posting this

Ahnueckh | 2007.10.17 09:03 AM

Helped me solved my problem
I got exaclty I want

Thank s :)

sucheta | 2007.12.06 10:32 PM

Here is a related bug I'm fighting in IE6 and IE7: If you set or change the value of a text input in its onkeyup, then onChange doesn't fire. By way of simple example:

If you remove onkeyup, then onChange fires when you leave the field. Otherwise, it doesn't. Any ideas why this is and how I can get around it? Maybe I should just use onBlur instead of onChange.

Sarah | 2008.01.22 08:05 AM

Sorry, the html didn't take. Let me try this:

input type="text" onkeyup="this.value = this.value" onChange="alert('onChange');"

Sarah | 2008.01.22 08:09 AM

In case anyone ever reads this ... here is the workaround I found.
My guess is that even though the user typed in the field, the fact that it was changed programmatically causes the browser to think that onChange doesn't need to fire.
So I have a javascript variable called origValue, and I do something like this ...

Obviously the onkeyup event isn't really doing anything in this case ... it was just the simplest case, for purposes of showing the bug.

Sarah | 2008.01.23 03:13 PM

Argh ... sorry, here is the html:
input type="text" onkeyup="this.value = this.value" onfocus="origValue = this.value;" onblur="if(this.value != origValue) doOnChangeStuff()"

Sarah | 2008.01.23 03:15 PM

Hi Sarah,

Sorry for the delay in responding - I've been out sick the last few days (today included). Thanks for describing the issue and coming back with a workaround. Lots of folks still wind-up on this three year old post looking for solutions to similar problems, so I suspect what you've provided will prove helpful to someone. Thanks again.

ewbi.develops | 2008.01.23 03:28 PM

This is closely related to the problem I'm encountering: onchange does not trigger if a user selected a text input value from the browser-supplied "dropdown" of recent values for fields of that name (IE calls that 'autofill'). Having read this page, it now makes some sense... the browser is programmatically changing the textbox value, rather than the user manually doing it.

That said, I'm not sure how best to address it. While it's obvious that "email" and probably "address", maybe "city" would suffer from this problem, how could I ever know what other fields might be affected? And I want to be sure every field doesn't have to process two javascript events... is "onblur" (only) the way to go, for ALL fields? (Note: the javascript in question is glomming all the template form fields into one big textarea.)

Very helpful page, thanks.

eon | 2008.03.04 10:17 AM

Oh, I forgot about auto-fill, eon. Thanks for mentioning it. I keep it turned off, but I'm not surprised to hear that selection of an auto-fill value doesn't trigger the onchange event.

Regarding your questions, I'd say that typically, if it isn't necessary to process field changes for visual effect, the solution is to process the entire set of field values on some finalizing activity, like a form postback triggered by a input button/submit click. Perhaps, in this scenario, an onblur handler would also be used to perform optional in-field data-based formatting/styling, if necessary.

However, when there is some visual effect requiring evaluation of each field as they are changed, as in the scenario you describe, I suppose one solution is to hang everything off the onblur and use separate state (e.g., JavaScript variables, hidden input elements, etc.) to retain original field values for comparison to determine whether they've changed (remembering, of course, to update the state when they do change in order to identify subsequent changes). Although, even in this scenario, the entire set of fields will probably need to be processed again on submit, as I think it is possible with default buttons and such to miss the onblur for the currently focused field.

Good luck!

ewbi.develops | 2008.03.04 11:00 AM

Thanks so much for the advice! For now, the onblur is working. We'll see what happens as I try to program for users who back up to the form to make further changes!

It took me almost 2 hours of searching to find this page, and nothing I found directly addressed the "auto-fill and onchange" issue. Perhaps now if anybody else comes across this issue, this page will rise to the top of their google results :-)

eon | 2008.03.04 12:21 PM

hi,

i have a related issue with onchange for textbox, i hope you
can help.

the onchange is not triggered when i enter a value in my
textbox past its maxlength and it changes its focus to a
different control. i expect that as the textbox loses
focus, it should call onchange (even if the focus was changed
automatically due to reaching the maxlength of the text control).

i have entered a different value for the textbox.

thanks in advance.

cha | 2008.06.16 08:54 PM

Hi cha,

Not much time to look at this today, but I wanted to clarify what you're asking. Neither of my browsers, IE and FireFox, *automatically* moves the focus from an input type=text once I've entered the maxlength number of characters. Focus simply remains in the textbox and I am prohibited from entering more characters. What browser are you using? Do you have any browser extensions loaded that might be affecting this behavior?

ewbi.develops | 2008.06.17 09:20 AM

hi ewbi,

thanks for the reply... but i've been using our own taglib
for implementations of our html controls like this input textbox. i just tested the behavior finding out that it behaves differently over the standard html input text tag. anyhow, i'll look into our own taglib now for a work-around.

thanks a lot for your time :-)

cha | 2008.06.18 01:07 AM

I have a different but related problem. I had my textboxes using onchange to submit an ajax request and it was working in IE 2 months ago. I made some changes and updates since then and mostly tested in Mozilla, then yesterday I fixed a bunch of stuff so the page would validate. Now when I try it in IE 6, I find that the onchange event is firing every time I click anywhere else after changing the text only once (manually). That's crazy!

I vaguely remember back when I got it to work, that there was a difference (for IE only) between onchange and onChange, so I had it as onChange. But that doesn't validate, so yesterday I switched to onchange. Now, of course, I encounter this problem and switch it back, but it doesn't make any difference. So my main problem is my memory!

I know there was something though, about the case of the keyword. But I just looked back through the log of transactions, and it wasn't doing this multi-submit thing before. I think I need a better version tracking system (I'm not using one). I just tried another page which I haven't modified (just the case of onChange), and it locks up the IE 6 browser when I enter text in the box. It won't let me leave the box, although it is firing the onchange event once. If I hit escape, it clears the box and is okay again.

So I have both problems to fix! It all works fine in Mozilla.

Joy | 2008.07.28 09:56 AM

Fortunately, I found a reference that described one of my problems: http://www.quirksmode.org/dom/events/change.html

It says "When you try to prevent the default action in IE5/6 the focus gets stuck."

So I took the "return false" part off of my onchange string, and it fixed both of my problems! (getting stuck and mult-submit). What a relief, but what a hassle to have to test in other browsers. I always wonder what bugs I'm missing by only trying it in Mozilla and IE 6. I also wonder if that is the type of thing I changed before and am remembering it being the case of the keyword. Oh well, it works now, and validates.

Joy | 2008.07.28 11:45 AM

Joy, that's good info - thanks for taking the time to share it here!

ewbi.develops | 2008.07.28 11:58 AM

it is a bug and it is not.
it's certainly not doing what we have in mind when we anticipate the goal of changing the data while they are still processed.
The problem is caused by the fact that MS anticipated that if you change (or change back) a value while edited, you would CANCEL the change. doing so, you would set the return value to FALSE

this fix the program:

function setValue(target) {
var iFieldId = document.getElementById("NextField");
alert("changed - value: " + target.value);
target.value += target.value;
iFieldId.focus ();
return false;
}


now in the SetValue function, if you CHANGE the value back (or simply change it as our goal here)
return false and set the focus where you want it.
if you DON'T modify anything, just return TRUE

Patrice | 2008.08.08 09:57 AM

Patrice, wow, can it really be that easy? Certainly makes sense - not sure why I didn't think to try it myself. Can't wait to check it out - thanks!

ewbi.develops | 2008.08.12 11:05 PM


TrackBack

TrackBack URL:  http://www.typepad.com/services/trackback/6a00d8341c7bd453ef00d83429a7ca53ef

Listed below are links to weblogs that reference IE: Changing a Textbox Value in its OnChange Event:

» Links: 6-20-2006 from Aaron Johnson
ewbi.develops: IE: Changing a Textbox Value in its OnChange Event Read the comments for a good discussion of the difference between IE & FF re: radio buttons and the onchange event. (categories: javascript onchange radio ) Unix FAQ -... [Read More]

Tracked on Jun 21, 2006 1:51:13 AM