简体   繁体   中英

preventDefault() in a keydown event, onchange event not trigger

The preventDefault() called in a keydown or keypress event with value programmatically changed does not consider changing and does not trigger the onchange event at the exit of the input text.

Example code:

$('#textbox1').on('change', function() {
    alert('onchange called');
});

$('#textbox1').on('keydown', function(event) {
    if(event.key=='a') {

      $(this).val('A');
      //event.target.value = 'A';
      event.preventDefault();
    }
});

After a call of onchange (leaving the input text) digit only the char 'a' and leaving the input another time.

Fiddle code: http://jsfiddle.net/gxx5744s/1/

What does use the onchange event to check if a value has changed? A pair of old / new value variables? a boolean? Can be possible interact with it?

Keydown event default probably also does this.

from the docs :

Depending on the kind of form element being changed and the way the user interacts with the element, the change event fires at a different moment:

  • When the element loses focus after its value was changed , but not commited (eg after editing the value of <textarea> or <input type="text"> ).

This is the case in your example.

Try changing the value and unfocus, you'll see the alert.

The onchange event normally is fired after you change the value of the text input when it then gets out of focus, as it is the case here too... But it is not fired when the function with the preventDefault is called, which is not quite the expected behaviour!!!

The preventDefault should prevent the default behaviour of the keydown event on which it is called not of the onchange event, which actually cannot be cancelled...

I guess the problem is something different:

The default setting of the value seems to differ from the JQuery way with

$(this).val('A');

Maybe because just the value for a submit is changed not the DOM element... If you change this line to

$(this).attr('Value','A');

it behaves as expected!

Interesting thing is, that the default behaviour is not setting the attribute value neither and both ways change the display too, but there must be a difference!

EDIT: To me the solution form @Kaddath seems to be most suitable:

 var change = false; $('#textbox1').on('change', function() { alert('onchange called'); }); $('#textbox1').on('blur', function() { if (change) { alert('"onchange" called too'); change = false; } }); $('#textbox1').on('keydown', function(event) { if (event.key == 'a') { $(this).val('A'); change = true; event.preventDefault(); } }); 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <input type="text" id="textbox1" /> 

Taking the idea of @Kaddath a revised solution a bit "dirty" but working might be. I do not like much but at the moment I did not find it better.

 $('#textbox1').on('change', function() { alert('onchange called'); }); $('#textbox1').on('keydown', function(event) { var oldValue = event.target.value; if (event.keyCode == 46) { //DELETE event.target.value = "" } else event.target.value = event.key + event.target.value; event.preventDefault(); if (event.target.valueOnFocus === undefined) { // set a new property on the input element event.target.valueOnFocus = oldValue; $(event.target).on('focus', function(event) { // From the second time that enter on the input element, // update the new property event.target.valueOnFocus = event.target.value; }); $(event.target).on('blur', function(event) { if (event.target.value !== event.target.valueOnFocus) $(event.target).trigger('change'); }); } }); 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <input type="text" id="textbox1" /> 

On fiddle: http://jsfiddle.net/gxx5744s/3/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM