virtuslab-open-source / formts Goto Github PK
View Code? Open in Web Editor NEWType-safe, declarative and performant React form & validation library
Home Page: https://virtuslab-open-source.github.io/formts/
License: MIT License
Type-safe, declarative and performant React form & validation library
Home Page: https://virtuslab-open-source.github.io/formts/
License: MIT License
consider adding built-in support for debouncing validation (useful for async validators) if this is not easy to to in userland currently.
add example with debounced async validation
from POC:
/**
* Will set the array field value to its copy with the item added at the end.
* Will run field validation with `change` trigger.
* Will set `isTouched` to `true`.
*/
pushItem: (item: E) => void;
/**
* Will set the array field value to its copy with the item at index `i` removed.
* Will run field validation with `change` trigger.
* Will set `isTouched` to `true`.
*/
removeItem: (i: number) => void;
example:
const [, form] = useFormts({ Schema });
const values = form.values
const onSubmit = form.getSubmitHandler((values) => console.log(values));
form.reset()
Check if validator API can be simplified
FormHandle.isSubmitting not being set to true while Promise received from submit onSuccess callback is processing
memoizing all possible expensive computations when validator is created and storing them in dictionary should help with perf
submitting should set touched of every field to true. Otherwise submitting does not reveal errors, if they are only visible for touched fields.
TypeError
Cannot convert undefined or null to object
at keys (node_modules/virtuslab/formts/dist/module/utils/object.js:26:17)
at deepMerge (node_modules/virtuslab/formts/dist/module/utils/object.js:100:10)
at eval (node_modules/virtuslab/formts/dist/module/utils/object.js:103:127)
at deepMerge (node_modules/virtuslab/formts/dist/module/utils/object.js:100:23)
at createInitialValues (node_modules/virtuslab/formts/dist/module/core/helpers/create-initial-values.js:14:46)
at getInitialState (node_modules/virtuslab/formts/dist/module/core/hooks/use-form-controller/formts-reducer.js:127:54)
touchField
is always triggered when setting a new value, but for the same field in 99% sets touched: true
when already touched: true
.
Add a check before setting touched
to skip setting the same value
Currently, automatic versioning only jumps by minor version regardless of the git history.
Maybe smth needs to be done to standard-version
configuration
consider using https://typedoc.org/ and running it as part of deploy_master pipeline to generate docs based on types and JSDocs comments. Add/Improve JSDocs if needed
createFormSchema
and createFormValidator
functions using builder pattern for better developer experiencefields
decoder container to top-level exportresearch and implement new version of API that allows for context-based hook usage and minimizing rerenders after atom-based implementation is ready
add ready to use validation functions base on https://codesandbox.io/s/formts-poc-3ryqv?file=/formts/src/validators/validators.ts
figure out a good way to expose the validators to the user:
import { required } from '@virtuslab/formts/validators
// that would be nicethis causes some problem in edge causes which can lead to returned initial values being initialised to illegal type (related to objects inside arrays)
rules
function receives values of fields listed in dependencies
array, if present
rules
function always receives all form values, regardless of dependencies
array. dependencies
purpose remains to specify other fields which trigger rerun of validation for given fields. This means that user will be able to use fields which do not trigger validation. Documentation and examples will need to be updated accordingly to make this behaviour obvious.
get rid of root
property for accessing non-primitive descriptor and simplify types
field
of type FieldHandleSchema
- object containing field handles for all form fieldsexample:
const [fields] = useFormts({ Schema });
const emailField = (
<input
value={fields.email.value}
onChange={e => fields.email.setValue(e.target.value)}
onBlur={fields.email.handleBlur}
/>
)
for example given the Schema:
const Schema = createFormSchema(
fields => ({
array: fields.array(
fields.object({
foo: fields.string(),
bar: fields.string(),
})
),
}),
);
it should be possible to attach validators to every array.foo
and array.bar
fields
dependencies
optionTransformation API for declarative mapping and filtering of field values
createFormTransformer
function (analogous to createFormValidator
)setValue
functionsetup examples directory (either app indexing all examples or 1 app per example)
FormSchema
typebuilt-in errors are awkward to use. Consider alternative approach where each built-in validation rule accepts exact error to be used.
benefits:
unionize
for error <=> error message decouplingwithError
helper can be removedadd codesandbox examples covering more advanced topics and features
make the lib truly view-layer agnostic by allowing usage outside of react or even without react altogether.
set stage for possible integration with other UI frameworks than react.
generic type T
in setFieldValue: <T>(field: GenericFieldDescriptor<T, Err>, value: T) => void;
is sometimes expanded by value
but it should be restricted by field
not technically a bug, since we provide field.touched
that can be used to hide errors, but can be annoying.
when FieldDescriptor of array or object field is passed into validate function then all of its children should be validated recursively so that in order to validate the whole form we need to validate top-level fields
Create cashe for atoms per path to share between rerenders and usages of useField
.
@virtuslab/formts
master
Simplify binding to onChange
function of various inputs by taking the responsibility of extracting value from event automatically using available runtime information - field type and input type
optionally also add parseEvent
function for extracting value from event without passing it to setValue
reset method for rolling back value to initial value, clearing touched flag and errors. Should propagate down on composite fields
object
field decoder that composes other decoders into an objectcreateFormSchema
functionbasic implementation of:
example:
const validator = createForm.validator(Schema, (validate) => [
validate({
field: Schema.userName,
rules: () => [required()]
}),
validate({
field: Schema.email,
rules: () => [
required(),
(email) => (/someregex/.test(email) ? null : "Invalid email address!")
]
})
]);
out of scope:
make sure that invoking setValue
for a field with no validation or only sync validation does not cause 2 re-renders
util function for composing multiple validation rules into one that runs all in paralel (rather than one after another until error is found)
placeholder for ideas/discussion
currently in order to use provided validation rules one has to import all as namespace.
this is not convenient and prevents tree-shaking of individual validation rule functions.
import { validators } from "@virtuslab/formts";
change the build config so that this is possible instead:
import { required, minLength } from "@virtuslab/formts/validators";
current solution:
fields.number()
corresponds to type number | ""
to represent empty input value as ""
fields.date()
corresponds to type Date | null
to represent lack of datefields.choice()
can accept ""
to represent empty select inputthis can be confusing and require additional casting of form state to domain models on submit.
research better solution
change/blur events of direct and indirect object and array field children should cause root validators to run
research & implement the most appropriate way to generate /dist
folder to make the lib consumable for widest possible audience.
Research & implement custom implementation of atoms as better alternative to form state management than plain React reducer & context
see POC: https://codesandbox.io/s/lens-based-form-poc-ydrhh?file=/src/state.tss
required by #51
ideally this would only change if there are any async validation rules for the field, but for MVP any implementation should be good enough
Replace usage of React useReducer
hook with atom based state.
This should allow for subscribing to just the required piece of form state for each hook.
requires #59
method for setting/clearing touched state on a field. Should propagate down on composite fields
Add runtime check to all hooks that passed FormSchema or FieldDescriptors matches the schema used in FormController
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.