Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ability to disable default blur handler #323

Open
kendallroth opened this issue Apr 29, 2022 · 6 comments
Open

Ability to disable default blur handler #323

kendallroth opened this issue Apr 29, 2022 · 6 comments
Labels
enhancement New feature or request

Comments

@kendallroth
Copy link

Summary 💡

Not all use cases may wish to have the Formik onBlur function called to touch fields when blurring. Ideally there would be a way to disable this behaviour (see motiviation section). I do not know whether it would be possible for users to disable this globally, or whether it might just need to respect the Formik validateOnBlur maybe, or another option all together?

Obviously this can be disabled "manually" by passing a custom no-op onBlur function; however, this would require passing a no-op to every textfield (or general MUI form component) or wrapping in a custom component (not awful, but not ideal).

Motivation 🔦

While common, calling the blur function automatically results in fields being "touched" on blur, while some people may wish to only have them touched on submit. For example, it may be desired to not see errors until after the initial submit, which is not possible currently (as fields are touched on blur).

@kendallroth kendallroth added the enhancement New feature or request label Apr 29, 2022
@cliedeman
Copy link
Collaborator

Hi @kendallroth
That functionality is actually built into formik.

https://github.com/jaredpalmer/formik/blob/b9cc2536a1edb9f2d69c4cd20ecf4fa0f8059ade/packages/formik/src/Formik.tsx#L691

I don't think this library can actually do anything about it.

@kendallroth
Copy link
Author

Yeah, I am definitely aware that it is built in to Formik (not a problem). What I am referring to specifically though is that it would be nice if there was a way to disable actually calling the onBlur function in this library.

For example, in the Formik docs mentioning MUI, the onBlur handler has been left entirely out (resulting in fields only being touched on submit). However, there is no way to disable the onBlur handler from being called in this library except by passing a custom onBlur handler to all fields (not ideal, although could wrap and copy prop definitions, etc...).

I was hoping there may be a way to maybe skip the default blur handler if validateOnBlur was false (from Formik), but this certainly might not be the most intuitive approach 😄. Otherwise, if there would be a way to disable globally (can think in Vue implementation, but not React at the moment 🤦), that would also work?

@kendallroth
Copy link
Author

kendallroth commented Apr 29, 2022

As a temporary (and awful 😉) workaround, I have used patch-package to persist manual changes to the dist/esm files.

Also, it looks like Select already has a no-op onBlur function instead of calling Formik, and a few others may as well?

P.S. Only linking this here for others who may wish to use a similar hacky approach vs passing no-ops everywhere or wrapping components (basically just laziness 🤦). It should not be considered a library recommendation at all!

diff --git a/node_modules/formik-mui/dist/esm/TextField.js b/node_modules/formik-mui/dist/esm/TextField.js
index 8c6a53c..a078ff7 100644
--- a/node_modules/formik-mui/dist/esm/TextField.js
+++ b/node_modules/formik-mui/dist/esm/TextField.js
@@ -7,9 +7,7 @@ function fieldToTextField(_a) {
     var disabled = _a.disabled, _b = _a.field, fieldOnBlur = _b.onBlur, field = __rest(_b, ["onBlur"]), _c = _a.form, isSubmitting = _c.isSubmitting, touched = _c.touched, errors = _c.errors, onBlur = _a.onBlur, helperText = _a.helperText, props = __rest(_a, ["disabled", "field", "form", "onBlur", "helperText"]);
     var fieldError = getIn(errors, field.name);
     var showError = getIn(touched, field.name) && !!fieldError;
-    return __assign(__assign({ error: showError, helperText: showError ? fieldError : helperText, disabled: disabled !== null && disabled !== void 0 ? disabled : isSubmitting, onBlur: onBlur !== null && onBlur !== void 0 ? onBlur : function (e) {
-            fieldOnBlur(e !== null && e !== void 0 ? e : field.name);
-        } }, field), props);
+    return __assign(__assign({ error: showError, helperText: showError ? fieldError : helperText, disabled: disabled !== null && disabled !== void 0 ? disabled : isSubmitting, onBlur: onBlur }, field), props);
 }
 function TextField(_a) {
     var children = _a.children, props = __rest(_a, ["children"]);
diff --git a/node_modules/formik-mui-lab/dist/esm/DatePicker.js b/node_modules/formik-mui-lab/dist/esm/DatePicker.js
index 49c5bd0..dd46e39 100644
--- a/node_modules/formik-mui-lab/dist/esm/DatePicker.js
+++ b/node_modules/formik-mui-lab/dist/esm/DatePicker.js
@@ -9,10 +9,7 @@ function fieldToDatePicker(_a) {
     var _b = _a.field; _b.onChange; var field = __rest(_b, ["onChange"]), _c = _a.form, isSubmitting = _c.isSubmitting, touched = _c.touched, errors = _c.errors, setFieldValue = _c.setFieldValue, setFieldError = _c.setFieldError, setFieldTouched = _c.setFieldTouched, _d = _a.textField, _e = _d === void 0 ? {} : _d, helperText = _e.helperText, onBlur = _e.onBlur, textField = __rest(_e, ["helperText", "onBlur"]), disabled = _a.disabled, label = _a.label, onChange = _a.onChange, onError = _a.onError, renderInput = _a.renderInput, props = __rest(_a, ["field", "form", "textField", "disabled", "label", "onChange", "onError", "renderInput"]);
     var fieldError = getIn(errors, field.name);
     var showError = getIn(touched, field.name) && !!fieldError;
-    return __assign(__assign({ renderInput: renderInput !== null && renderInput !== void 0 ? renderInput : (function (params) { return (React.createElement(TextField, __assign({}, params, { error: showError, helperText: showError ? fieldError : helperText, label: label, onBlur: onBlur !== null && onBlur !== void 0 ? onBlur : function () {
-                setFieldTouched(field.name, true, true);
-            } }, textField))); }), disabled: disabled !== null && disabled !== void 0 ? disabled : isSubmitting, onChange: onChange !== null && onChange !== void 0 ? onChange : function (date) {
-            setFieldTouched(field.name, true, false);
+    return __assign(__assign({ renderInput: renderInput !== null && renderInput !== void 0 ? renderInput : (function (params) { return (React.createElement(TextField, __assign({}, params, { error: showError, helperText: showError ? fieldError : helperText, label: label, onBlur: onBlur }, textField))); }), disabled: disabled !== null && disabled !== void 0 ? disabled : isSubmitting, onChange: onChange !== null && onChange !== void 0 ? onChange : function (date) {
             setFieldValue(field.name, date, true);
         }, onError: onError !== null && onError !== void 0 ? onError : createErrorHandler(fieldError, field.name, setFieldError) }, field), props);
 }

@cliedeman
Copy link
Collaborator

I have managed to avoid this so far but I thought we might eventually need it.

We could create a Context that allows users to customize beaviour

interface FormikMuiContextType {
  disableSubmitLoading: boolean,
  disableDefaultBlurHandler: boolean,
}

const FormikMuiContext = React.createContext({
  // defaults
  disableSubmitLoading: false,
  disableDefaultBlurHandler: false,
})

Then users can customize behaviour globaly or per form or component

(Select is probably an oversight)

@kendallroth
Copy link
Author

kendallroth commented Apr 29, 2022

Gotcha, yeah, something like that could be nice (if it didn't introduce too much overhead).

On the other hand, I honestly just usually wrap Formik components myself (as I only use a few of them) and apply this behaviour in that manner. This library was really easy to get up and running and saved that time though (thanks for putting it together 🎉)! And I could just wrap the component as well, but that felt a little extra/unnecessary if there was something else (although using patch-package feels like a step down honestly 🤣).

P.S. If the no-op on Select was an oversight, it certainly made my life a bit easier (one less component to hack). Given that select fields work a bit differently than text fields, might it have been intentional? On the other hand, the date picker does set touched directly as well, so maybe not too different than text fields?

@cliedeman
Copy link
Collaborator

I actually use a mixture of both. I have several projects using it and some of the more complicated components (Autocomplete) is really tricky to do right. But yes the core goal is to get people going quickly

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants