Formik: Custom onBlur on Field overrides default behavior

Created on 29 Mar 2018  路  9Comments  路  Source: formium/formik

Bug, Feature, or Question?

Bug/Feature

Current Behavior

a Field with a custom onBlur removes the default validation/touched behavior

<Field name="fname" onBlur={() => console.log("custom")} />

https://codesandbox.io/s/yk9mmj1kwx

Desired Behavior

custom onBlur prop will be chained to the internal handleBlur

Suggested Solutions

in handleBlur

if (this.props.onBlur) this.props.onBlur()

stale

Most helpful comment

How about this?

function formikOnBlur(evt) {
  // formiks default handler
}

function getFieldProps(props) {
  return {
    ...props,
    onBlur: (...args) => {
      formikOnBlur(...args);
      props.onBlur && props.onBlur(...args);
    },
    // ... other props
  };
}

<Field name="email">
  {field => (
    <input
      {...field.getFieldProps({
        onBlur: () => console.log('blur'),
      })}
    />
  )}
</Field>

props getter would chain "overrides" props while still keeps Formik work.

All 9 comments

Hrmmm. Need to think about this one

This is why I didn't want to make a PR first ;)
If it's too breaking, how about another preserveBlurBehavior boolean?

Hola! So here's the deal, between open source and my day job and life and what not, I have a lot to manage, so I use a GitHub bot to automate a few things here and there. This particular GitHub bot is going to mark this as stale because it has not had recent activity for a while. It will be closed if no further activity occurs in a few days. Do not take this personally--seriously--this is a completely automated action. If this is a mistake, just make a comment, DM me, send a carrier pidgeon, or a smoke signal.

ProBot automatically closed this due to inactivity. Holler if this is a mistake, and we'll re-open it.

This would be nice - I'd like to prefill another field based on the content of another, after onBlur.

Here's my solution with the Formik's field.onBlur prop. Wrapped Formik's onBlur handler with my own. Had to resort to a setTimeout as it seems field.touched and field.errors aren't immediately available after formik's onBlur event is called:

...
<Field name={name} id={name} component={CustomInputText} />
...

class CustomInputText extends React.PureComponent {
    handleBlur = e => {
        const {
            field: { name, onBlur },
        } = this.props;

        onBlur(e);

        // The latest touched and errors aren't available until after the
        // formik's onBlur handler has been called. Setting a timeout allows us
        // to access the proper touched and errors after onBlur event has
        // occurred.
        setTimeout(() => {
            const {
                form: { touched, errors },
            } = this.props;
            const isError = touched[name] && errors[name];
            const isSuccess = touched[name] && !errors[name];

            if (isError) {
                console.log('validation error');
            }

            if (isSuccess) {
                console.log('validation success');
            }
        }, 0);
    };

    render() {
        const { field, ...otherProps } = this.props;

        return (
            <input
                className="floating-field"
                type="text"
                {...field}
                {...otherProps}
                onBlur={this.handleBlur}
            />
        );
    }
}

How about this?

function formikOnBlur(evt) {
  // formiks default handler
}

function getFieldProps(props) {
  return {
    ...props,
    onBlur: (...args) => {
      formikOnBlur(...args);
      props.onBlur && props.onBlur(...args);
    },
    // ... other props
  };
}

<Field name="email">
  {field => (
    <input
      {...field.getFieldProps({
        onBlur: () => console.log('blur'),
      })}
    />
  )}
</Field>

props getter would chain "overrides" props while still keeps Formik work.

This would be a really helpful feature for interactions like this one.

giphy

I'm a big fan of the approach outlined by @Andreyco. This would follow the 'prop getters' pattern as is outlined here: https://kentcdodds.com/blog/how-to-give-rendering-control-to-users-with-prop-getters

It's used to great effect in https://github.com/downshift-js/downshift

Was this page helpful?
0 / 5 - 0 ratings