Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # ~~`BaseEntityEditor2.0`~~ Form
- Hello!
- We build frontend and there's no way we can run away from building ***forms***. We started with `FormFields`. Later, `BaseEntityEditor` emerged as the solution to render forms. Today, we have more than **130** components using `BaseEntityEditor`. Since the inception of `BaseEntityEditor`, not much has changed ( okay - we added resolution of values , extracted out utils for creating handlers & validations, added a lot of fieldRenderers, created `RepeatableEditors` - to improve DX ). But we have turned a blind eye to a lot of general problems that people face while using `BaseEntityEditor` ( may be we complained but we never fixed, not living the Sprinklr way! )
- But today, we are listening and we have our eyes open. We figured out some basic problems our hardworking devs face while creating a form and we have tried to address these problems.
- First up, we are renaming `BaseEntityEditor` to `Form` ( hurray!!!! ) because yeah, it's a form.
- That's the only trivial change, I promise. Let's look at the real problems.
- - `onAction` -- for basic cases where the changes in form were to be set in values as is, i.e. without any transformation to other `values` or `errors`, `fields` & `layouts`, the devs would still have to implement an `onAction` to be passed down to `BaseEntityEditor`.
- Majority of us implemented this by using `connectActions` and then passing it `actionHandlers` which handled the actionType - `ON_FIELD_CHANGE`.
- ```
- // v1
- function SimpleBabyEditor({ values, errors, onAction }){
- return (
- <div>
- <BaseEntityEditor
- values={values}
- errors={errors}
- onAction={onAction}
- fields={FIELDS}
- layouts={LAYOUTS}
- />
- <button
- onClick={() => onAction({type: 'SAVE_BABY'})}
- >
- Save Baby
- </button>
- </div>
- );
- }
- const actionHandlers = {
- [actionType.ON_FIELD_CHANGE]: getOnFieldChangeHandler(), // core/containers/baseEntityEditor/utils/handlers
- SAVE_BABY(action, { getState, setState }){
- const { values } = getState();
- const errors = getErrors(values); // to be noted - point(1)
- if(errors){
- setState({ errors });
- } else {
- console.log('submitted', values);
- }
- },
- DEFAULT(action, { getState }){
- return getState().onAction(action);
- }
- };
- export default connectActions(
- actionHandlers,
- actionHandlers.DEFAULT,
- ({baby}) => adaptBabyToValues(baby)
- )(BabyEditor)
- ```
- We have created `useForm` to solve this. The new way to do it:
- ```
- // v2
- function SimpleBabyEditor({ baby }){
- const { values, errors, handleAction, handleSubmit } = useForm({
- initialValues: adaptBabyToValues(baby),
- onSubmit: (_values) => console.log('submitted', _values),
- });
- return (
- <div>
- <Form
- values={values}
- errors={errors}
- fields={FIELDS}
- layouts={LAYOUTS}
- onAction={handleAction}
- />
- <button
- onClick={handleSubmit}
- >
- Save Baby
- </button>
- </div>
- );
- }
- ```
- Yes, we did miss out on calculating errors in `v2`. Let's look at validations.
- - validations - So far, everybody had to calculate the errors on their own. If we look at the example above (`point(1)`), `getErrors` would be something like:
- ```
- function getErrors(values){
- const ruleSet = RuleSet.create();
- ruleSet.push(getMandatoryFieldRule('babyName'));
- return ruleSet.validate(values);
- }
- ```
- This meant, everybody had to implement their way of validating the entity against some rules and it was the devs' responsibility to extract out the errors when the user submits.
- Now, with `useForm` and the newly created `spr-base/lib/validationSchema`, the validation would look like:
- ```
- function SimpleBabyEditor({ baby }){
- const { values, errors, handleAction, handleSubmit } = useForm({
- initialValues: adaptBabyToValues(baby),
- onSubmit: (_values) => console.log('submitted', _values),
- validationSchema: vs.object({
- babyName: vs.string().required()
- }),
- });
- return (
- <div>
- <Form
- values={values}
- errors={errors}
- fields={FIELDS}
- layouts={LAYOUTS}
- onAction={handleAction}
- />
- <button
- onClick={handleSubmit}
- >
- Save Baby
- </button>
- </div>
- );
- }
- ```
- The validations will run when the user submits and if there are errors, the validations will run each time the values change.
- - Scrolling to the errors
- When using `useForm`, the user gets scrolled to the errors whenever they submit the form. For this to work, we have created `useFormField` hook ( `FormField` renderProp component for class components ) to be used by the field renderers. All you have to do is set the `ref` on your **field renderers** container. e.g. :
- ```
- function BabyNameInput({id, value, placeholder, label }){
- const { fieldRef, onChange } = useFormField(id);
- return (
- <div ref={fieldRef /* set the ref on your container el */}>
- <p>{label}</p>
- <input
- type="text"
- value={value}
- onChange={ e => onChange(e.target.value)}
- />
- </div>
- }
- ```
- <br />
- <br />
- `useForm` and `validationSchema` are created to support the entire spectrum of cases - basic to advanced. We request you to give them a try and let us know what you think.
- <br />
- Happy Easy Coding
- <br />
- August 1, 2019
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement