24

There is a lot of contents on this in stack overflow but none seems to work for my case. I have an input text field and I want to simulate keypress event to fill the text field.

Reason: I am automating a lot of data entry task on a web interface which provides no API. Changing the input field using .value does not trigger the JS side (angular) of the interface. That is why I want to simulate keypress event.

First I tried this:

var inp = document.getElementById('rule-type');
inp.dispatchEvent(new KeyboardEvent('keypress',{'key':'a'}));

Then I learned in Chrome the key and code stays as 0 and does not change in KeyBoardEvent.

So I created seperate event ev = new KeyboardEvent('keypress',{'key':'a', 'code': 'KeyA'})

And then I dispatched again, the return statement is true but it does not change the input field.

The solution needs to be in pure javascript not jQuery.

sjishan
  • 3,392
  • 9
  • 29
  • 53

3 Answers3

27

You will not be able to fire an event that will cause text to populate an input. See this snippet from MDN:

Note: manually firing an event does not generate the default action associated with that event. For example, manually firing a key event does not cause that letter to appear in a focused text input. In the case of UI events, this is important for security reasons, as it prevents scripts from simulating user actions that interact with the browser itself.

Thanks @gforce301

Your best bet may be to set the value and then dispatch an event.

zero298
  • 25,467
  • 10
  • 75
  • 100
  • curious. why keydown? also your code is KeyA, key and keyCode is different. anyways after dispatching it wont change the text field. – sjishan May 07 '18 at 18:07
  • 5
    @sjishan A manually fired keyboard event will never change the value of the input. See: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent note about half way down on manually fired events. This is for security reasons. – gforce301 May 07 '18 at 18:16
  • @gforce301 Good note. I have updated my answer. If you'd rather me delete my answer so that you could post that yourself, let me know. – zero298 May 07 '18 at 18:25
  • 1
    thanks that was very informative. regarding your suggestion of setting the value and then dispatch the event. it wont work because since as soon as I set the value and then even if i do any manual data entry it does not work. – sjishan May 07 '18 at 18:29
  • can this be done using UI events ? I tried this ev = new UIEvent('input', {'inputType': 'insertText', 'data':'a', isTrusted: true}) but given those parameters are read only it does not allow me to change – sjishan May 07 '18 at 18:31
  • 1
    Thanks to zero298 and @gforce301. This answer saves my day! – yaobin May 30 '19 at 18:24
  • @yaobin ikr I thought I was going crazy until I found this page! – nmu May 14 '21 at 13:28
25

IMHO you're going about this all wrong. Angular is not "listening" to keypress or the like. It is listening to change and input events. See the example below. It does (admittedly it is simple) what you need.

var iButton = document.getElementById('inputButton');
iButton.addEventListener('click', simulateInput);

var cButton = document.getElementById('changeButton');
cButton.addEventListener('click', simulateChange);

function simulateInput() {
  var inp = document.getElementById('name');
  var ev = new Event('input');
  
  inp.value =inp.value + 'a';
  inp.dispatchEvent(ev);
}

function simulateChange() {
  var inp = document.getElementById('name');
  var ev = new Event('change');
  
  inp.value = 'changed';
  inp.dispatchEvent(ev);
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="">
 
<p>Input something in the input box:</p>
<p>Name : <input id="name" type="text" ng-model="name" placeholder="Enter name here"></p>
<h1>Hello {{name}}</h1>

</div>

<button id="inputButton">I simulate the "input" event.</button>
<button id="changeButton">I simulate the "change" event.</button>
gforce301
  • 2,944
  • 1
  • 19
  • 24
  • tried. didn't work. getting the same error. ApiException: [LocalizedErrorWrapper>] if I make any change using `.value` it just does not work anymore. – sjishan May 07 '18 at 18:47
  • @sjishan I'm not an Angular expert. The example I gave is a minimal Angular app and as you can see the example works. Your error says: "StringLengthError.TOO_SHORT @ name". Maybe try putting in a string of a valid length? – gforce301 May 07 '18 at 18:51
  • it is of valid length. the reason it is saying too short is because it could not register the change. if i put the same string manually after refreshing the page it works fine. quite interestingly if i do not refresh and do manual entry after changing with `value` it still throws the same error. – sjishan May 07 '18 at 18:55
  • @sjishan Also, what do you mean by "getting the same error"? Your post mentions nothing about getting an error. If the error is the problem then you should have asked about the error, instead of turning this into a [XY Problem](https://mywiki.wooledge.org/XyProblem) – gforce301 May 07 '18 at 18:56
  • You're right its probably the XY Problem situation. I keep getting this LocalizedErrorWrapper – sjishan May 07 '18 at 19:10
  • @sjishan At this point I think you're going to have to provide a [MCVE](https://stackoverflow.com/help/mcve) for us to help. – gforce301 May 07 '18 at 19:36
12

To automate filling <input> and <textarea> values and automatically dispatch all needed events you need:

  1. focus the input\textarea
  2. run document.execCommand with insertText command
let inputElement = document.getElementsById('rule-type');
inputElement.focus();
document.execCommand('insertText', false, 'input value');

With this method input\textarea value modification should be captured by all major frameworks including Angular an Vuejs. This modification will be processed by frameworks the same way as if user pressed "Paste" option in browser main menu.

Eugene Mala
  • 1,081
  • 12
  • 25