final-form icon indicating copy to clipboard operation
final-form copied to clipboard

Trim whitespace on fields before validate / onSubmit

Open davnicwil opened this issue 5 years ago • 2 comments

Are you submitting a bug report or a feature request?

Possibly a feature request, more a question: what I want may already exist :-)

What is the current behavior?

I want to trim the values of specified fields before they are passed to validate and onSubmit, but allow them to contain the leading/trailing spaces in the actual values in the form.

Example UX Scenario: imagine a user pastes a value into an input, and that copied value contains leading and/or trailing spaces. I want to allow that, and even display that (I don't want to do anything fancy like mutate the actual value and auto-remove the spaces, just leave it as it is) but when the values are validated and submitted I want to just ignore any leading/trailing whitespace.

Right now, I'm doing this with a higher-order function that wraps validate and onSubmit at the form level - it looks like this:

(Note this code is React specific, but obviously this could be applied to any final-form library implementation)

const buildTrimWhitespaceHOF = (fields) => (validateOrOnSubmit) => (values) => {
  // trim specified fields
  fields.forEach((field) => {
    const value = values[field]

    if (value && value.trim) values[field] = value.trim()
  })

  // pass trimmed values on to validate or onSubmit
  return validateOrOnSubmit(values)
}

// builds HOF to trim whitespace on fields 'foo' and 'bar'
const trimWhitespace = buildTrimWhitespaceFunction([ 'foo', 'bar' ])

- - -

<Form
    onSubmit={trimWhitespace(onSubmit)} // wrap with the HOF to trim whitespace on specified fields
    validate={trimWhitespace(validate)}
  >
  ... fields including 'foo' and 'bar' ...
</Form>

What is the expected behavior?

What I'd like is a way to set this up using FieldProps, on the field level, so it's more declarative. I suppose what I'm really after is a prop that modifies whatever value is passed for that Field to both validate and onSubmit.

I initially thought this might be the behaviour of parse, but was wrong - parse actually modifies the value in the form field itself, which I don't want. The reason is as above - I want to trim only when validating and submitting, but actually allow leading and trailing spaces in the form, for a more natural UX.

Is there a Field prop that does anything like this - or at a completely different, better way than what I'm doing above that achieves the same thing?

If no, how do you feel about implementing such a prop? Like, maybe even specifically to trim, as this is probably a very common requirement for forms. I'd imagine it looking something like this:

(Again, React, but just a prop so I believe the core library is the right place to be asking this)

// trim foo and bar for validate and onSubmit, but *not* password
<Field name="foo" trim>...</Field>
<Field name="bar" trim>...</Field>
<Field name="password">...</Field>

Happy to implement this as a PR, for further evaluation of the idea in practice, should you think it might be worth exploring further.

davnicwil avatar Jul 11 '19 13:07 davnicwil

Hey @erikras did you get a chance to look at this? Maybe it's a quick one - sorry to bug you I'm just curious to know! :-)

davnicwil avatar Jul 27 '19 17:07 davnicwil

I think you want more or less what I want, a way to alter a field's value before it reaches onSubmit : https://github.com/final-form/react-final-form/issues/136#issuecomment-524254496

Right now Erik doesn't seem convinced by the idea.

I really think that there are two "models", the one for maintaining the inputs' state, which we can elegantly manipulate using parse/format at the fields level, and the one that we actually submit to some remote API. Unfortunatly, we can't manipulate the second model at the field level right now, our only option is to centralize everything inside onSubmit, which feels weird to me.

I really like final-form's performance by default, and the parse/format feature which I missed with formik. I'll try to push the idea on formik too, we'll see! 😄

jgoux avatar Aug 26 '19 13:08 jgoux