final-form / final-form-focus

🏁 Final Form "decorator" that will attempt to apply focus to the first field with an error upon an attempted form submission
MIT License
83 stars 15 forks source link

Provide custom focus implementation #13

Open likerRr opened 5 years ago

likerRr commented 5 years ago

feature request

It would be nice to specify focus implementation. For example to make smooth scroll to element + Npx above it before focusing:

import createDecorator from 'final-form-focus'

const onFocus = input => {
  const { top } = getOffset(input);
  const scrollTop = top - 50;

  window.scrollTo({
    top: scrollTop,
    behavior: 'smooth',
  });

  input.focus();
}

const focusOnErrors = createDecorator(null, null, onFocus)
AndyOGo commented 4 years ago

@erikras Any plans to support custom focus implementations?

mattrabe commented 4 years ago

My team has rolled its own solution for this, which focuses on the input and smooth-scrolls to it using scrollIntoView. Therefore, we stopped using this library. Our solutions looks like this:

import React from 'react'
import { Form as FinalForm } from 'react-final-form'

const Form = props => (
  <FinalForm {...props}>
    {({
      form: finalFormApi,
      handleSubmit,
    }) => (
      <form
        finalFormApi={finalFormApi}
        {...props}
        onSubmit={event => {
          const invalidField = finalFormApi.getRegisteredFields().find(field => finalFormApi.getFieldState(field).invalid)

          if (invalidField) {
            const targetInput = document.querySelector(`[name="${invalidField}"]`)
            const targetLabel = document.querySelector(`label[for="${invalidField}"]`) || targetInput
            if (targetInput) {
              targetInput.focus({ preventScroll: true })
              targetLabel.scrollIntoView({
                behavior: 'smooth',
                block: 'center',
              })
            }
          }

          handleSubmit(event)
        }}
      >
        {props.children}
      </form>
    )}
  </FinalForm>
)

export default Form
TheRusskiy commented 3 years ago

FYI, here's a PR for this: https://github.com/final-form/final-form-focus/pull/25