Advertisement
Guest User

Untitled

a guest
Aug 19th, 2019
111
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.39 KB | None | 0 0
  1. # ~~`BaseEntityEditor2.0`~~ Form
  2.  
  3. Hello!
  4. 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! )
  5.  
  6. 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.
  7.  
  8. First up, we are renaming `BaseEntityEditor` to `Form` ( hurray!!!! ) because yeah, it's a form.
  9.  
  10. That's the only trivial change, I promise. Let's look at the real problems.
  11.  
  12. - `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`.
  13.  
  14. Majority of us implemented this by using `connectActions` and then passing it `actionHandlers` which handled the actionType - `ON_FIELD_CHANGE`.
  15.  
  16. ```
  17. // v1
  18. function SimpleBabyEditor({ values, errors, onAction }){
  19. return (
  20. <div>
  21. <BaseEntityEditor
  22. values={values}
  23. errors={errors}
  24. onAction={onAction}
  25. fields={FIELDS}
  26. layouts={LAYOUTS}
  27. />
  28. <button
  29. onClick={() => onAction({type: 'SAVE_BABY'})}
  30. >
  31. Save Baby
  32. </button>
  33. </div>
  34. );
  35. }
  36. const actionHandlers = {
  37. [actionType.ON_FIELD_CHANGE]: getOnFieldChangeHandler(), // core/containers/baseEntityEditor/utils/handlers
  38. SAVE_BABY(action, { getState, setState }){
  39. const { values } = getState();
  40. const errors = getErrors(values); // to be noted - point(1)
  41. if(errors){
  42. setState({ errors });
  43. } else {
  44. console.log('submitted', values);
  45. }
  46. },
  47. DEFAULT(action, { getState }){
  48. return getState().onAction(action);
  49. }
  50. };
  51. export default connectActions(
  52. actionHandlers,
  53. actionHandlers.DEFAULT,
  54. ({baby}) => adaptBabyToValues(baby)
  55. )(BabyEditor)
  56. ```
  57.  
  58. We have created `useForm` to solve this. The new way to do it:
  59.  
  60. ```
  61. // v2
  62. function SimpleBabyEditor({ baby }){
  63. const { values, errors, handleAction, handleSubmit } = useForm({
  64. initialValues: adaptBabyToValues(baby),
  65. onSubmit: (_values) => console.log('submitted', _values),
  66. });
  67.  
  68. return (
  69. <div>
  70. <Form
  71. values={values}
  72. errors={errors}
  73. fields={FIELDS}
  74. layouts={LAYOUTS}
  75. onAction={handleAction}
  76. />
  77. <button
  78. onClick={handleSubmit}
  79. >
  80. Save Baby
  81. </button>
  82. </div>
  83. );
  84. }
  85. ```
  86. Yes, we did miss out on calculating errors in `v2`. Let's look at validations.
  87. - 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:
  88.  
  89. ```
  90. function getErrors(values){
  91. const ruleSet = RuleSet.create();
  92. ruleSet.push(getMandatoryFieldRule('babyName'));
  93. return ruleSet.validate(values);
  94. }
  95. ```
  96. 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.
  97.  
  98. Now, with `useForm` and the newly created `spr-base/lib/validationSchema`, the validation would look like:
  99. ```
  100. function SimpleBabyEditor({ baby }){
  101. const { values, errors, handleAction, handleSubmit } = useForm({
  102. initialValues: adaptBabyToValues(baby),
  103. onSubmit: (_values) => console.log('submitted', _values),
  104. validationSchema: vs.object({
  105. babyName: vs.string().required()
  106. }),
  107. });
  108.  
  109. return (
  110. <div>
  111. <Form
  112. values={values}
  113. errors={errors}
  114. fields={FIELDS}
  115. layouts={LAYOUTS}
  116. onAction={handleAction}
  117. />
  118. <button
  119. onClick={handleSubmit}
  120. >
  121. Save Baby
  122. </button>
  123. </div>
  124. );
  125. }
  126. ```
  127.  
  128. The validations will run when the user submits and if there are errors, the validations will run each time the values change.
  129. - Scrolling to the errors
  130.  
  131. 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. :
  132. ```
  133. function BabyNameInput({id, value, placeholder, label }){
  134. const { fieldRef, onChange } = useFormField(id);
  135.  
  136. return (
  137. <div ref={fieldRef /* set the ref on your container el */}>
  138. <p>{label}</p>
  139. <input
  140. type="text"
  141. value={value}
  142. onChange={ e => onChange(e.target.value)}
  143. />
  144. </div>
  145. }
  146. ```
  147. <br />
  148. <br />
  149.  
  150. `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.
  151. <br />
  152.  
  153. Happy Easy Coding
  154. <br />
  155. August 1, 2019
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement