redux-form: Set focus in first faulty field
Hi,
is there a way to always set the focus to the first faulty field?
I tried to implement a solution in my render field component:
componentDidUpdate() {
const { meta: { submitting, touched, error } } = this.props;
const field = this.refs['field' + this.props.name];
...
if (!submitting && touched && error) {
field.select();
}
}
This works partially, but…
If I enter one char in the first faulty field, the validation is at this moment valid for the field and the next faulty field steals my focus.
How can I prevent this or is there already a built-in solution?
Thanks for your help!
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Reactions: 1
- Comments: 16 (5 by maintainers)
All suggestions (in all corresponding/found issues) for implementing focusing the first field error were failing for me… then I worked out why… when using
redux-form/immutable
theonSubmitFail
errors
object does not contain the fields in registration order (possibly requires an ordered list reviver when setting/getting fields?).Also most do numerous DOM queries (query per field). So I solved it with one single DOM query:
In
onSubmitFail
Get all the error’ed fields and query them usingquerySelector
. This is the most workable/optimal asquerySelector
“Returns the first Element within the document that matches the specified selector, or group of selectors.” … so even if the selector is not in field order… it still returns the first error’ed field in the document, then justfocus()
it.Could possibly also
scrollIntoView()
though in my case this failed as the site has a fixed/floating header.Example
Notes
flattenObject
actually creates correct field names#1336 #488
I just recently started using
redux-forms
. I am working on an existing project that is using version 6.8.0. (Based on the implementation and the v7 docs, I think it will work in v7 too.)This solution uses 2 utility functions and the
onSubmitFail
callback.There are two main steps that need to be done for each form:
name
attribute to theform
element (just reuse the unique one you give toreduxForm
)onSubmitFail
callback as illustrated above.This solution solves all the issues I believe have been plaguing everyone.
redux-form
.Notes:
redux-forms
(but I am pretty sure it should work).focusFirstInvalidControl
can be used in any HTML document regardless of it being generated by React.Please let me know if these utilities already exist in an npm package somewhere. If not and you have a cleaner implementation (maybe one that doesn’t use recursion), then please let me know.
Edit: I whipped up an npm package that will set focus on the first invalid control. See qc-dom_utils. You can use the following in place of the
FormUtils.js
module above.Edit: I searched in npm and I searched the redux-form code base, but I didn’t find anything to flatten the errors. So, I created the qc-redux-form_utils package.
Thanks for the details, @AubreyHewes!
Since this issue is very UI specific, it’s not a concern of Redux Form, therefore I’m closing it. Feel free to continue the discussion, though.
I’ve been working on this today and found a solution which I think is a bit more elegant than using
document.querySelectorAll
, and (with limited testing) seems to work well. In theonSubmitFail
method I dispatch thefocus
action so theactive
prop of the first failing field is set:Then in the component I pass to
Field
, I set the focus on the<input>
tag incomponentDidUpdate
via a ref:If that looks useful and works for other folks then I can put in a PR with some documentation on how to do this.