'Javascript - Simulate Keyboard Input into AngularJS Form

Hi I'm working on a Chrome Extension that executes a content script in pure Javascript where I could simulate keypresses into Inputs.

However the site I'm trying to simulate keypresses into is running AngularJS.

The Form

Here's the HTML code of the form and the input. Note the ng-untouched, ng-pristine, ng-valid classes on the elements.

<form _ngcontent-ysv-c110="" novalidate="" class="ng-untouched ng-pristine ng-valid">
    <esw-address _ngcontent-ysv-c110="">
       <esw-address-my _nghost-ysv-c130="">
          <div _ngcontent-ysv-c130="" class="address-form ng-untouched ng-pristine ng-invalid">

             <esw-input _ngcontent-ysv-c130="" type="text" eswtrim="" class="address-form__firstName ng-untouched ng-pristine ng-invalid" _nghost-ysv-c109="" maxlength="60">
                
                <!-- THIS INPUT -->
                <input _ngcontent-ysv-c109="" triggers="manual" class="textInput ng-untouched ng-pristine ng-invalid" id="firstName" type="text" placeholder="First Name" required="" maxlength="60">
             
            </esw-input>

          </div>
       </esw-address-my>
    </esw-address>
    <button _ngcontent-ysv-c110="" type="button" translate="" class="button-continue">Save Continue</button>
 </form>

The Code I'm Using

Currently the way I try to simulate keypresses into this input is by running the following code:

var firstNameV = "Alex";
var firstName = document.getElementById('firstName');
firstName.focus();
var firstNameV = addressObj['firstName'];
for (let i = 0; i < firstNameV.length; i++) {
    var char = firstNameV[i];
    firstName.dispatchEvent(new KeyboardEvent('keydown', { 'key': char }));
    firstName.value += char;
    firstName.dispatchEvent(new KeyboardEvent('keyup', { 'key': char }));
    await sleep(10);
}

Problem

However when I go ahead and submit the form, the fields light up red as the elements did not change from ng-untouched to ng-touched or ng-pristine to ng-dirty.

So my question, is there a way to properly simulate typing into an AngularJS input in order to trigger the 'touched' event and pass form validation so I could submit the form?

Also I'd like to add that I do not have access to the angular / $scope variables in Javascript. Thus, I'm not sure what I can do.



Solution 1:[1]

Following solution helped me 99% of time. Mostly the change event needs to be triggered.

EDIT: For a better example please provide a stackblitz example. Without knowing your Website I cant reproduce it and only can guess.

$("#testButton").on("click", function (e) {
fillField('testInput', "Stackoverflow rocks!", false)
})


function fillField(id, value, select) {
  let element = document.getElementById(id);
  if (element) {
    element.focus();
    if (!select && element.value.length == 0) {
      simulateTyping(element, value, 0);
    } else {
      let event = new Event("change");
      element.value = value;
      element.dispatchEvent(event);
    }
    element.blur();
  }
}


function simulateTyping(element, value, i) {
  if (i < value.length) {
    element.value += value.charAt(i);
    element.dispatchEvent(new Event("change"));
    setTimeout(() => {
      i++;
      simulateTyping(element, value, i);
    }, 20);
  }
}
* {
    box-sizing: border-box;
}

.body {
    font-family: Arial, sans-serif;
    font-size: 14px;
    line-height: 20px;
    color: #333;
}

.form {
    display: block;
    margin: 0 0 15px;
}

.email-form {
    display: block;
    margin-top: 20px;
    margin-left: 20px;
}

.button {
    height: 40px;
    display: inline-block;
    padding: 9px 15px;
    background-color: grey;
    color: white;
    border: 0;
    line-height: inherit;
    text-decoration: none;
    cursor: pointer;
}

.input {
    display: inline-block;
    width: 200px;
    height: 40px;
    margin-bottom: 0px;
    padding: 9px 12px;
    color: #333333;
    vertical-align: middle;
    background-color: #ffffff;
    border: 1px solid #cccccc;
    margin: 0;
    line-height: 1.42857143;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>
<body class="body">
    <div class="form">
        <form class="email-form"><input type="text" id="testInput" class="input"><a href="#" id="testButton" class="button">GO</a></form>
    </div>
</body>

</html>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1