3

Every year, I have a spreadsheet of ~100 rows I need to submit to a site through a clunky form one row at a time. Instead of wasting my time filling the form by hand 100 times, I wasted my time writing some JavaScript that would take care of it.

The code has served me well for 3 years, but now they've upgraded to an Angular JS app, and now I'm unsure how to fill the forms as if they've been filled by a human.

Take this Angular form for example https://codepen.io/sevilayha/full/xFcdI/

Before I'd be able to set the values of the elements, click on them to ensure a dirty state is triggered, click submit, and be done, but with Angular apps that doesn't seem to work:

function setAndClick(selector, value) {
  const el = document.querySelector(selector);
  el.value = value;
  el.click();
}
setAndClick('[name="name"]', 'Happy Robot');
setAndClick('[name="username"]', 'happyrobot');
setAndClick('[name="email"]', '[email protected]');

Manually click on the fields after they've been filled by a script does trigger a dirty state, but I can't find any event (change, keyup, keydown, etc) that can trigger it programatically.

How can I successfully fill and submit a form in an Angular App with vanilla JavaScript?

1
  • angular has a $digest cycle where it matches the state of the variables backing the ng-model for each form element with the state of the input. Programmatically changing the input doesn't trigger the $digest, and thus outside changes aren't reflected, and anything that does trigger the $digest could potentially wipe out these outside changes. You'll have to hook into the angular app on the page and manually trigger the $digest using $scope.$apply(), but at that point, you probably should just directly change the variable values, rather than inject the values into the inputs. Commented Jun 20, 2017 at 23:56

1 Answer 1

3

A useful insight could be that for any element in the DOM you can get its angular scope by doing:

angular.element(theElement).scope()

You can then use this scope to do all sorts of things from outside the angular app itsef, such as what you're trying to do here. It is particularly useful for trying to debug an angular app from the developer tools.

As a quick demo of this technique, I have tweaked your Pen to set the Name field:

https://codepen.io/anon/pen/pwPdqM

The function that does the work is:

function dirtyByCode() {
  // Get the input element wrapped up as an angular element
  var elName = angular.element(document.getElementsByName("name")[0]);
  // Get the angular scope for this element
  var $scope = elName.scope();
  // Call $setViewValue, which also sets the dirty state.
  $scope.userForm.name.$setViewValue("Simon");
  // Call render to update the form itself.
  elName.controller("ngModel").$render();
}

An advantage of doing it like this is you don't need to use $apply or worry about the $digest cycle.

Sign up to request clarification or add additional context in comments.

1 Comment

What if I do not have access to the angular variable?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.