What is the best way to trigger onchange event in js response

Good afternoon.

We use the backhone + reactjs package to create a client application. Relying heavily on the notorious value of Link, we distribute the values ​​directly to the model through our own shell, which supports the js interface for two-way binding.

Now we are faced with a problem:

We have a jquery.mask.js plugin that formatly enters an input value, so it does not fire React events. All this leads to a situation when the model receives unformatted values ​​from user input and skips the formatted ones from the plugin.

React seems to have many browser-specific event handling strategies. Is there any general way to trigger a change event for a specific DOM element so that React hears it?

+42
reactjs
May 27 '14 at 14:49
source share
8 answers

At least on text inputs, it seems that onChange listening for input events:

 var event = new Event('input', { bubbles: true }); element.dispatchEvent(event); 
+50
Jun 25 '15 at 16:43
source share

I know this answer comes a little late, but I recently ran into a similar problem. I wanted to trigger an event on a nested component. I had a list with widgets like “radio” and “checkbox” (they were divs that behaved like checkboxes and / or switches), and in some other place of the application, if someone closed the toolbar, I needed uncheck it.

I found a fairly simple solution, not sure if this is the best practice, but it works.

 var event = new MouseEvent('click', { 'view': window, 'bubbles': true, 'cancelable': false }); var node = document.getElementById('nodeMyComponentsEventIsConnectedTo'); node.dispatchEvent(event); 

This triggered a click event on domNode, and my handler connected through a reaction was actually called so that it behaves as I would expect if someone clicked on an element. I have not tested onChange, but it should work, and I'm not sure how this will be true in really old versions of IE, but I believe that MouseEvent is supported, at least in IE9 and higher.

In the end, I moved away from this for my specific use case, because my component was very small (only part of my application was used, since I'm still learning it), and I could achieve the same thing differently without getting links to dom.

UPDATE:

As other comments pointed out, it is better to use this.refs.refname to get a link to the dom node. In this case, refname is the link that you linked to your component via <MyComponent ref='refname' /> .

+18
Oct 20 '14 at 9:46
source share

For React 16 and React> = 15.6

Setter .value= does not work as we would like, because the React library overrides the parameter for inputting values, but we can call the function directly in the context of input .

 var nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value").set; nativeInputValueSetter.call(input, 'react 16 value'); var ev2 = new Event('input', { bubbles: true}); input.dispatchEvent(ev2); 

For a textarea element, you must use the prototype of the HTMLTextAreaElement class.

New codepen example .

All loans to this depositor and his decision

Deprecated answer only for React <= 15.5

With react-dom ^15.6.0 you can use the simulated flag for an event object to pass the event through

 var ev = new Event('input', { bubbles: true}); ev.simulated = true; element.value = 'Something new'; element.dispatchEvent(ev); 

I made a codepen with an example

To understand why a new flag is needed, I found this comment very useful:

React's input logic now deduplicates changes, so they do not fire more than once per value. It listens on both browser onChange / onInput events, as well as DOM node value sets (when updating the value via javascript). This has a side effect of the value, if you update the input value manually input.value = 'foo', then send a ChangeEvent with {target: input} React will register as a set and event, see its value still `` foo ', consider its a duplicate event and internalize it.

This works fine in normal cases, because the "real" browser is triggered, the event does not cause a set on the element. Value. You can help out this logic secretly by marking the event that you are triggering using a simulated flag and the reaction will always trigger the event. https://github.com/jquense/react/blob/9a93af4411a8e880bbc05392ccf2b195c97502d1/src/renderers/dom/client/eventPlugins/ChangeEventPlugin.js#L128

+14
Sep 02 '17 at 9:05 on
source share

You can simulate events using ReactTestUtils , but designed for unit testing.

I would recommend not using valueLink for this case and just listen to the change events triggered by the plugin and update the input status in response. Bidirectional binding is used as a demo than anything else; they are included in add-ons only to emphasize the fact that pure two-way binding is not suitable for most applications and that more application logic is usually required to describe interactions in your application.

+6
May 27 '14 at 18:28
source share

Triggering change events on arbitrary elements creates dependencies between components that are difficult to talk about. It's best to stick with a one-way React data stream.

There is no simple snippet to trigger a React change event. The logic is implemented in ChangeEventPlugin.js, and there are different code branches for different input types and browsers. Moreover, implementation details vary across versions of React.

I built react-trigger-change that does this, but is intended for testing, and not as a production dependency:

 let node; ReactDOM.render( <input onChange={() => console.log('changed')} ref={(input) => { node = input; }} />, mountNode ); reactTriggerChange(node); // 'changed' is logged 

Codepen

+1
Apr 11 '17 at 10:14 on
source share

If you are using Backbone and React, I would recommend one of the following options:

They help integrate Backbone models and collections with React views. You can use Backbone events the same way you do with Backbone views. I played in both cases and did not see much difference, except for one - mixin, and the other React.createClass changes - React.createBackboneClass .

0
Sep 04 '14 at 12:50
source share

since we use functions to handle the onchange event, we can do this as follows:

 class Form extends Component { constructor(props) { super(props); this.handlePasswordChange = this.handlePasswordChange.bind(this); this.state = { password: '' } } aForceChange() { // something happened and a passwordChange // needs to be triggered!! // simple, just call the onChange handler this.handlePasswordChange('my password'); } handlePasswordChange(value) { // do something } render() { return ( <input type="text" value={this.state.password} onChange={changeEvent => this.handlePasswordChange(changeEvent.target.value)} /> ); } } 
0
Apr 27 '17 at 7:32
source share

An extension of the answer from Grin / Dan Abramov, this works on several types of input. Tested in React> = 15.5

 const inputTypes = [ window.HTMLInputElement, window.HTMLSelectElement, window.HTMLTextAreaElement, ]; export const triggerInputChange = (node, value = '') => { // only process the change on elements we know have a value setter in their constructor if ( inputTypes.indexOf(node.__proto__.constructor) >-1 ) { const setValue = Object.getOwnPropertyDescriptor(node.__proto__, 'value').set; const event = new Event('input', { bubbles: true }); setValue.call(node, value); node.dispatchEvent(event); } }; 
0
Nov 21 '17 at 9:17
source share



All Articles