I am building a chrome extension which needs to be able to change the value of a text field in what I believe is a ReactJS webpage (I'm writing the content script which executes in the page), but the traditional ways that would do so won't work (they change the value of the input, but they don't seem to trigger whatever event the website uses to update its (likely) useState variable. i've thrown the kitchen sink at it:
field.value = 'new value";
field.setAttribute('value', field.value);
field.dispatchEvent(new KeyboardEvent('keypress', {'key': 'H', bubbles: true}));
field.dispatchEvent(new KeyboardEvent('keydown', {'key': 'H', bubbles: true}));
field.dispatchEvent(new KeyboardEvent('keyup', {'key': 'H', bubbles: true}));
field.dispatchEvent(new Event('change', {bubbles: true}));
field.dispatchEvent(new Event('blur', {bubbles: true}));
field.dispatchEvent(new Event('textInput', {bubbles: true}));
field.dispatchEvent(new Event('hashchange', {bubbles: true}));
field.dispatchEvent(new Event('selectionchange', {bubbles: true}));
field.dispatchEvent(new InputEvent('input', {bubbles: true}));
document.dispatchEvent(new KeyboardEvent('keypress', {'key': 'H', bubbles: true}));
document.dispatchEvent(new KeyboardEvent('keydown', {'key': 'H', bubbles: true}));
document.dispatchEvent(new KeyboardEvent('keyup', {'key': 'H', bubbles: true}));
document.dispatchEvent(new Event('change', {bubbles: true}));
document.dispatchEvent(new Event('blur', {bubbles: true}));
document.dispatchEvent(new Event('textInput', {bubbles: true}));
document.dispatchEvent(new Event('hashchange', {bubbles: true}));
document.dispatchEvent(new Event('selectionchange', {bubbles: true}));
document.dispatchEvent(new InputEvent('input', {bubbles: true}));
I've also tried building a formal KeyboardEvent as follows:
field.dispatchEvent(new KeyboardEvent("keypress", {
key: "e",
keyCode: 69, // example values.
code: "KeyE", // put everything you need in this object.
which: 69,
shiftKey: false, // you don't need to include values
ctrlKey: false, // if you aren't going to use them.
metaKey: false // these are here for example's sake.
}));
and with
var keyboardEvent = document.createEvent('KeyboardEvent');
var initMethod = typeof keyboardEvent.initKeyboardEvent !== 'undefined' ? 'initKeyboardEvent' : 'initKeyEvent';
keyboardEvent[initMethod](
'keydown', // event type: keydown, keyup, keypress
true, // bubbles
true, // cancelable
window, // view: should be window
false, // ctrlKey
false, // altKey
false, // shiftKey
false, // metaKey
40, // keyCode: unsigned long - the virtual key code, else 0
0, // charCode: unsigned long - the Unicode character associated with the depressed key, else 0
);
field.dispatchEvent(keyboardEvent);
with no success. When the field is blurred, it returns to the original non-changed stat, although manually changing it works.
I have noticed that
document.execCommand('insertText', false, "new value");
does work, but I don't want to use it as it appears to be deprecated.
Any suggestions?
I'd prefer to do this in vanilla JS, but open to libraries if necessary.
You need to get the actual value setter using Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value").set
and call it, see the example below (where the react code sets the input value to 'hi'
, and we (outside of react) set it to whatever
, which changes both the input we set, and the label which is also rendering the value):
// Example stateless functional component
const SFC = props => {
const [v, setV] = React.useState('hi');
return (
<div>{v}:<br/> <input value={v} onChange={(e) => setV(e.target.value) } /></div>
);
}
// Render it
ReactDOM.render(
<SFC />,
document.getElementById("root")
);
const newValue = 'whatever';
var input = document.querySelector("input");
var nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value").set;
nativeInputValueSetter.call(input, newValue);
var ev2 = new Event('input', { bubbles: true});
input.dispatchEvent(ev2);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>