I have a Form
ponent that I am building in React and this form has some Field
ponents as children. I am using these ponents to build a log in form that has an email address and password. My form has an onSubmit
handler that serializes its children (Field
s) and sends off an AJAX request.
Everything is working well in the normal case. But, when browsers like Chrome Autofill the form with my email address and password, the serialization doesn't pick up the values of the inputs.
Field
currently looks something like this:
/** @jsx React.DOM */
var Field = React.createClass({
serialize: function() {
return { name: this.props.name, value: this.refs.field.state.value };
},
render: function() {
return (
<div>
<label>
{this.props.label}
<input type={this.props.type} ref="field"
name={this.props.name}
defaultValue={this.props.value} />
</label>
</div>
)
}
});
How do I get the browser Autofill value to show up in my serialized Field
data?
I have a Form
ponent that I am building in React and this form has some Field
ponents as children. I am using these ponents to build a log in form that has an email address and password. My form has an onSubmit
handler that serializes its children (Field
s) and sends off an AJAX request.
Everything is working well in the normal case. But, when browsers like Chrome Autofill the form with my email address and password, the serialization doesn't pick up the values of the inputs.
Field
currently looks something like this:
/** @jsx React.DOM */
var Field = React.createClass({
serialize: function() {
return { name: this.props.name, value: this.refs.field.state.value };
},
render: function() {
return (
<div>
<label>
{this.props.label}
<input type={this.props.type} ref="field"
name={this.props.name}
defaultValue={this.props.value} />
</label>
</div>
)
}
});
How do I get the browser Autofill value to show up in my serialized Field
data?
3 Answers
Reset to default 3State should flow in one direction, from the top layer down to the bottom. So reaching into a child element to get its state is a bad idea. To acplish the serialization with this structure, you simply need to reach into the DOM to get the value of the input. In the code example above, the serialize
method should be:
serialize: function() {
return { name: this.props.name, value: this.refs.field.getDOMNode().value };
},
Using onChange event is the most mon scenario to update whatever model property bound to a ponent, but you can also use onBlur to catch the values when the form is "auto-filled" by the browser.
var Input = React.createClass({
getInitialState: function() {
return {typed: ''};
},
onBlur: function(event) {
this.setState({typed: event.target.value});
},
render: function() {
return <div>
<input type="text" onBlur={this.onBlur.bind(this)}/>
You typed: <code>{this.state.typed}</code>
</div>
}
});
This is my solution using refs :) ..basically I trigger the change events manually for the first second..the reason behind is that every browser is handling autofill in a different way and this changes based on browser version..there is no way to cover this properly as of now
ponentDidMount () {
let tries = 4;
this.int = setInterval(() => {
tries--;
if (tries === 0) {
this._createChangeEvent();
clearInterval(this.int);
}
}, 300);
}
_createChangeEvent = () => {
if ("createEvent" in document) {
const evt = document.createEvent("HTMLEvents");
evt.initEvent("change", false, true);
this.input.dispatchEvent(evt);
} else {
this.input.fireEvent("onchange");
}
};