Skip to content

Commit

Permalink
Add ability to disable blur validation (#136)
Browse files Browse the repository at this point in the history
* add nullish coalescing support

* add ability to disable on blur validation

* fix redundant calls of blur validation
  • Loading branch information
wsmd authored May 17, 2020
1 parent 5932047 commit 60ec7f7
Show file tree
Hide file tree
Showing 6 changed files with 720 additions and 479 deletions.
4 changes: 4 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
"no-underscore-dangle": ["error", { "allow": ["__DEV__"] }]
},
"overrides": [
{
"files": ["**/*.js"],
"parser": "babel-eslint"
},
{
"files": ["test/**/*.js"],
"rules": {
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
- [Labels](#labels)
- [Custom Controls](#custom-controls)
- [Updating Fields Manually](#updating-fields-manually)
- [Resetting The Formm State](#resetting-the-form-state)
- [Resetting The Form State](#resetting-the-form-state)
- [Working with TypeScript](#working-with-typescript)
- [API](#api)
- [`initialState`](#initialstate)
Expand Down Expand Up @@ -591,7 +591,7 @@ formState.reset(); // resetting the form state

#### `formOptions.validateOnBlur`

When set to `true`, all form fields will validated when the input loses focus. If not specified, the `validate` function of each input will be called on value change.
By default, input validation is performed on both of the `change` and the `blur` events. Setting `validateOnBlur` to `true` will limit input validation to be **only** performed on `blur` (when the input loses focus). When set to `false`, input validation will **only** be performed on `change`.

#### `formOptions.withIds`

Expand Down Expand Up @@ -742,7 +742,7 @@ The following options can be passed:
| `onBlur(e): void` | Optional. A blur event handler that's called with the input's `blur` [`SyntheticEvent`](https://reactjs.org/docs/events.html). |
| `validate(value, values, e): any` | Optional (required for `raw` inputs). An input validation function that determines whether the input value is valid. It's called with the input value, all input values in the form, and the change/blur event (or the raw value of the control in the case of `.raw()`). The input is considered **valid** if this method returns `true` or `undefined`. Any [truthy value](https://developer.mozilla.org/en-US/docs/Glossary/Truthy) other than `true` returned from this method will make the input **invalid**. Such values are used a **custom validation errors** that can be retrieved from [`state.errors`](#form-state). HTML5 validation rules are ignored when this function is specified. |
| `compare(initialValue, value): any` | Optional (required for `raw` inputs). A comparison function that determines whether the input value is pristine. It's called with the input's initial value, and the input's current value. It must return a boolean indicating whether the form is pristine. |
| `validateOnBlur: boolean` | Optional. `false` by default. When set to `true` and the `validate` function is provided, the function will be called when the input loses focus. If not specified, the `validate` function will be called on value change. |
| `validateOnBlur: boolean` | Optional. Unspecified by default. When unspecified, input validation is performed on both of the `change` and the `blur` events. Setting `validateOnBlur` to `true` will limit input validation to be **only** performed on `blur` (when the input loses focus). When set to `false`, input validation will **only** be performed on `change`. |
| `touchOnChange: boolean` | Optional. `false` by default. When `false`, the input will be marked as touched when the `onBlur()` event handler is called. For custom controls that do not support `onBlur`, setting this to `true` will make it so inputs will be marked as touched when `onChange()` is called instead. |

## License
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,15 @@
"@babel/cli": "^7.1.2",
"@babel/core": "^7.1.2",
"@babel/plugin-transform-runtime": "^7.3.4",
"@babel/preset-env": "^7.1.0",
"@babel/preset-env": "^7.9.6",
"@babel/preset-react": "^7.0.0",
"@rollup/plugin-babel": "^5.0.0",
"@rollup/plugin-replace": "^2.3.2",
"@types/jest": "^24.0.11",
"@types/react": "^16.8.4",
"@wsmd/eslint-config": "^1.2.0",
"babel-core": "^7.0.0-bridge.0",
"babel-eslint": "^10.1.0",
"babel-jest": "^23.6.0",
"coveralls": "^3.0.9",
"eslint": "^6.8.0",
Expand Down
18 changes: 10 additions & 8 deletions src/useFormState.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export default function useFormState(initialState, options) {

const formState = useState({ initialState });
const { getIdProp } = useInputId(formOptions.withIds);
const { set: setDirty, has: isDirty } = useCache();
const { set: setDirty, get: isDirty } = useCache();
const callbacks = useCache();
const devWarnings = useCache();

Expand Down Expand Up @@ -141,6 +141,10 @@ export default function useFormState(initialState, options) {

formState.comparators.set(name, getCompareFn());

function getValidateOnBlur() {
return formOptions.validateOnBlur ?? inputOptions.validateOnBlur;
}

function validate(
e,
value = isRaw ? formState.current.values[name] : e.target.value,
Expand Down Expand Up @@ -284,11 +288,7 @@ export default function useFormState(initialState, options) {

formOptions.onChange(e, formState.current.values, newValues);

const validateOnBlur = formOptions.validateOnBlur
? inputOptions.validateOnBlur !== false
: inputOptions.validateOnBlur;

if (!validateOnBlur) {
if (!getValidateOnBlur()) {
validate(e, value, newValues);
}

Expand All @@ -307,10 +307,12 @@ export default function useFormState(initialState, options) {
* A) when it's either touched for the first time
* B) when it's marked as dirty due to a value change
*/
/* istanbul ignore else */
if (!formState.current.touched[name] || isDirty(name)) {
validate(e);
setDirty(name, false);
// http://github.com/wsmd/react-use-form-state/issues/127#issuecomment-597989364
if (getValidateOnBlur() ?? true) {
validate(e);
}
}
}),
...getIdProp('id', name, ownValue),
Expand Down
11 changes: 11 additions & 0 deletions test/useFormState-validation.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,17 @@ describe('passing a custom input validate function', () => {
);
});

it('does not validate input on blur when validateOnBlur is false', () => {
const validate = jest.fn(() => false);
const { change, blur } = renderWithFormState(([, { text }]) => (
<input {...text({ name: 'name', validate, validateOnBlur: false })} />
));
change({ value: 'test' });
expect(validate).toHaveBeenCalled();
blur();
expect(validate).toHaveBeenCalledTimes(1);
});

it('marks input as valid', () => {
const { change, formState } = renderWithFormState(([, { text }]) => (
<input
Expand Down
Loading

0 comments on commit 60ec7f7

Please sign in to comment.