5

"react": "^15.4.2"

I am having trouble triggering the change event from jquery for an input rendered with React. I need to do this for some end to end testing.

here's a sandbox as a full showcase: https://codesandbox.io/s/pp1k1kq3om with jquery already loaded.

If you run : $('#reactSlider').val(50).change() in the console, you'll notice that the change handler isn't called.

In the sandbox above there's also a pure html slider for comparison, that one works as expected (change function is called).

also tried to dispatch a new event like this:

var event = new Event('change') var target = $('#reactSlider')[0]; target.dispatchEvent(event); 

The above doesn't work either (and does work on the pure html slider).

import React from "react"; import { render } from "react-dom"; const changeHandler = event => { alert(`react slider changed:${event.target.value}`); }; const App = () => ( <div> <label htmlFor="reactSlider">react-slider</label> <input id="reactSlider" type="range" onChange={changeHandler} min={10} max={100} step={10} value={20} /> <p>run in the console: $('#reactSlider').val(50).change()</p> <br /> <br /> <p>Notice that for the React slider, the change event is not triggered.</p> </div> ); render(<App />, document.getElementById("root")); 
5
  • jQuery registers/handles its own event listeners and does not call non-jQuery event listeners when called programmatically. Commented Apr 11, 2018 at 19:47
  • The best thing to do here would be to have a single function that executes whatever you want to execute on the change, and call that function from within your changeHandler and also call it independently when you change the value programmatically. If you need to be able to handle change events from the console, set up a separate jQuery event handler that captures the change event and then call your function from within there Commented Apr 11, 2018 at 19:51
  • @mhodges unfortunately, doing what you suggested would defeat my testing purpose, I'm looking for a way to interact with the react rendered input and trigger it's react change event listener. Any chance of being able to do that ? Commented Apr 11, 2018 at 20:00
  • Possible duplicate of How can I trigger an onchange event manually? Commented Apr 11, 2018 at 20:09
  • doesn't look like a duplicate, i've tried dispatching a new event, still doesn't trigger the react event listener. Commented Apr 11, 2018 at 20:45

3 Answers 3

0

This is a way to trigger an event:

function triggerInput(enteredName, enteredValue) { console.log(enteredValue); const input = document.getElementById(enteredName); const lastValue = input.value; input.value = enteredValue; const event = new Event("input", { bubbles: true }); const tracker = input._valueTracker; if (tracker) { tracker.setValue(lastValue); } input.dispatchEvent(event); } window.addEventListener("load", function() { triggerInput("reactSlider", 40); }); 

Courtesy to https://jetrockets.com/blog/onchange-trigger-example-with-react

Full code:

import React from 'react'; const changeHandler = event => { alert(`react slider changed:${event.target.value}`); }; export function App(props) { return ( <div> <label htmlFor="reactSlider">react-slider</label> <input id="reactSlider" type="range" onChange={changeHandler} min={10} max={100} step={10} value={20} /> <p>run in the console: $('#reactSlider').val(50).change()</p> <br /> <br /> <p>Notice that for the React slider, the change event is not triggered.</p> </div> ); } // Log to console console.log('Hello console') function triggerInput(enteredName, enteredValue) { console.log(enteredValue); const input = document.getElementById(enteredName); const lastValue = input.value; input.value = enteredValue; const event = new Event("input", { bubbles: true }); const tracker = input._valueTracker; if (tracker) { tracker.setValue(lastValue); } input.dispatchEvent(event); } window.addEventListener("load", function() { triggerInput("reactSlider", 40); }); 

Running this on code sandbox triggers the event successfully:

enter image description here

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

1 Comment

Doesn't work anymore with React 17.0.2.
0

This works. Inspired by Simulate click event on react element

async function simulateMouseClick(el, newValue) { const nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value').set; nativeInputValueSetter.call(elements, newValue); let opts = {view: window, bubbles: true, cancelable: true, buttons: 1}; el.dispatchEvent(new MouseEvent("mousedown", opts)); await new Promise(r => setTimeout(r, 50)); el.dispatchEvent(new MouseEvent("mouseup", opts)); el.dispatchEvent(new MouseEvent("click", opts)); } 

Then use as follows:

let btn = document.querySelector("#reactSlider"); await simulateMouseClick(btn, 3); 

Comments

-1

Ok, so I've found sort of a workaround. it looks like the onInput event can be triggered just fine. In the case of input type='range' the "input" event is triggered in the same situation as the "change" is so I was able to switch it.

Workaround would be: use onInput instead of onChange and trigger it like this:

function triggerChange(selector,evt) { let ev = new Event(evt, { bubbles: true }); let el = $(selector)[0] el.dispatchEvent(ev); }; triggerChange('#reactSlider','input'); 

1 Comment

No longer works on more recent versions of React.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.