Skip to content

Commit 0c43933

Browse files
committed
Allow validators to return undefined
1 parent fd6a75b commit 0c43933

File tree

6 files changed

+44
-23
lines changed

6 files changed

+44
-23
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
# 1.2.14 (07/04/2021)
2+
3+
- Moved `yupValidator` to seperate package [`typed-react-form-yup`](https://www.npmjs.com/package/typed-react-form-yup)
4+
- Child/array forms name prop only allows object fields now.
5+
- Pass FormEvent through `form.handleSubmit`
6+
- Allow string as argument to setErrors, which sets the error on the parent.
7+
- Allow validators to return undefined.
8+
19
# 1.2.13 (07/04/2021)
210

311
- The `name` prop on FormTextArea and FormSelect did not get passed to their input element.

README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ A fast, completely type-checked React form state manager, focussed on typescript
66

77
- [Object fields](https://typed-react-form.codestix.nl/docs/Object-fields)
88
- [Array fields](https://typed-react-form.codestix.nl/docs/Array-fields)
9-
- [Validation and yup integration](https://typed-react-form.codestix.nl/docs/Validation)
9+
- [Validation](https://typed-react-form.codestix.nl/docs/Validation)
1010
- [Easily toggle fields](https://typed-react-form.codestix.nl/docs/Toggling-a-field)
1111
- [Listeners (subscription based state updates)](https://typed-react-form.codestix.nl/docs/useListener)
1212

@@ -30,9 +30,10 @@ This library is built from the ground up for React with typescript, but it also
3030

3131
Contributions are always welcome!
3232

33-
To begin developing yourself, clone this repo, and do the following:
34-
- `/`: contains the library source code. Use `yarn start` or `npm run start` to watch the files and build each time something changes. This way the testing application gets updated each time.
35-
- `example/`: contains the testing application. Use `yarn start` or `npm run start` in the example directory to start the application.
33+
1. Clone this repo
34+
2. Install deps using `yarn`. Yarn is required due to the resolutions field in package.json, npm does not support this.
35+
3. Open a new terminal and navigate to `example/`, run `yarn` and `yarn start` to start the testing application.
36+
4. Done! When you edit source code, it will be rebuilt and update the testing application.
3637

3738
## License
3839

example/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
"react-router-dom": "^5.2.0",
2323
"react-scripts": "link:../node_modules/react-scripts",
2424
"styled-components": "^5.2.1",
25-
"typed-object-validator": "^1.0.1",
25+
"typed-object-validator": "^1.0.2",
2626
"typed-react-form": "link:..",
2727
"typed-react-form-yup": "^1.0.0",
2828
"typescript": "link:../node_modules/typescript",

example/src/App.tsx

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ import {
1515
useArrayForm
1616
} from "typed-react-form";
1717
import { VisualRender } from "./VisualRender";
18-
import * as yup from "yup";
19-
import { yupValidator } from "typed-react-form-yup";
18+
// import * as yup from "yup";
19+
// import { yupValidator } from "typed-react-form-yup";
20+
import tv from "typed-object-validator";
2021

2122
interface ExampleFormData {
2223
id: number;
@@ -82,16 +83,26 @@ const initialValues: ExampleFormData = {
8283
todos: [{ message: "This is a todo", priority: "normal" }]
8384
};
8485

85-
const TodoListSchema = yup.object({
86-
name: yup.string().required("Enter a name").min(5, "Enter a longer name"),
87-
language: yup.string().oneOf(["en", "nl"], "Must be english or dutch"),
88-
todos: yup.array().of(
89-
yup.object({
90-
message: yup.string().required("Enter a todo")
86+
const TodoListSchema = tv.object({
87+
name: tv.string().min(5, "Enter a longer name"),
88+
language: tv.value("en").or(tv.value("nl", "Must be english or dutch")),
89+
todos: tv.array(
90+
tv.object({
91+
message: tv.string().min(1, "Enter a todo")
9192
})
9293
)
9394
});
9495

96+
// const TodoListSchema = yup.object({
97+
// name: yup.string().required("Enter a name").min(5, "Enter a longer name"),
98+
// language: yup.string().oneOf(["en", "nl"], "Must be english or dutch"),
99+
// todos: yup.array().of(
100+
// yup.object({
101+
// message: yup.string().required("Enter a todo")
102+
// })
103+
// )
104+
// });
105+
95106
export function ArrayTest() {
96107
const [values, setValues] = useState({ name: "a list", items: ["asdf"] });
97108
const form = useForm(values);
@@ -128,7 +139,7 @@ export function ArrayTest() {
128139
export function Form() {
129140
const form = useForm(
130141
initialValues, // <- Default values, may change
131-
yupValidator(TodoListSchema, { abortEarly: false }), // <- Validator (optional)
142+
(values) => TodoListSchema.validate(values),
132143
false, // <- Validate on change (optional)
133144
false // <- Validate on mount (optional)
134145
);

example/yarn.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10308,10 +10308,10 @@ type@^2.0.0:
1030810308
resolved "https://registry.yarnpkg.com/type/-/type-2.1.0.tgz#9bdc22c648cf8cf86dd23d32336a41cfb6475e3f"
1030910309
integrity sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA==
1031010310

10311-
typed-object-validator@^1.0.1:
10312-
version "1.0.1"
10313-
resolved "https://registry.yarnpkg.com/typed-object-validator/-/typed-object-validator-1.0.1.tgz#524184eec5da5a37a90ea3011877b05189e9faee"
10314-
integrity sha512-6h0PJeLVW7J9O65HqgotnDxatlwY652+kuA+yU3CPtJTlP+TJAmLHQ4NrqXwSqnwvNTfd54OuUCTrV6if7g+Mw==
10311+
typed-object-validator@^1.0.2:
10312+
version "1.0.2"
10313+
resolved "https://registry.yarnpkg.com/typed-object-validator/-/typed-object-validator-1.0.2.tgz#19ae734eedeca91a06f1535445ed8188509ba149"
10314+
integrity sha512-6A9qDfEViI7lB41LjAGsO7MvupvQJg6Yu1V8DWwEjfWhDuZZCD145UfZLMWM3Ani6a53jE2LbjLhn8FCXjejfg==
1031510315

1031610316
typed-react-form-yup@^1.0.0:
1031710317
version "1.0.0"

src/form.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
export type ListenerCallback = () => void;
22
export type ListenerMap = { [T in string]?: ListenerCallback };
3-
export type Validator<T, Error> = (values: T) => ErrorType<T, Error> | Promise<ErrorType<T, Error>>;
3+
export type Validator<T, Error> = (values: T) => ErrorType<T, Error> | undefined | Promise<ErrorType<T, Error> | undefined>;
44

55
export type ChildFormMap<T extends object, State, Error extends string> = {
66
[K in KeysOfType<T, object>]?: ChildFormState<T, K, State, Error>;
@@ -307,7 +307,7 @@ export class FormState<T extends object, State = DefaultState, Error extends str
307307
if (!this.validator) return true;
308308
let r = this.validator(this.values);
309309
if (r instanceof Promise) r = await r;
310-
this.setErrors(r);
310+
this.setErrors(r ?? ({} as ErrorType<T, Error>));
311311
return !this.error;
312312
}
313313

@@ -320,7 +320,7 @@ export class FormState<T extends object, State = DefaultState, Error extends str
320320
let r = this.validator(this.values);
321321
if (r instanceof Promise)
322322
throw new Error("validateSync() was called on a form with an asynchronous validator set, please use `await form.validate()` instead.");
323-
this.setErrors(r);
323+
this.setErrors(r ?? ({} as ErrorType<T, Error>));
324324
return !this.error;
325325
}
326326

@@ -371,7 +371,7 @@ export class FormState<T extends object, State = DefaultState, Error extends str
371371
if (notifyParent && this instanceof ChildFormState) {
372372
this.parent.setError(this.name, errors, false, true);
373373
}
374-
errors = {} as any;
374+
errors = {} as ErrorType<T, Error>;
375375
} else {
376376
addDistinct(keys, Object.keys(errors));
377377
}
@@ -387,8 +387,9 @@ export class FormState<T extends object, State = DefaultState, Error extends str
387387
false, // Will call this.parent.setError by itself after all values have been copied, see 3 lines down
388388
false // Will call fireAnyListener by itself after all values have been copied, see 3 lines down
389389
)
390-
)
390+
) {
391391
changed = true;
392+
}
392393
}
393394
if (!changed) return false;
394395

0 commit comments

Comments
 (0)