# Form Builder WebApp - DATOMS
## packages that will be used
- [react-draggable](https://www.npmjs.com/package/react-draggable) for draggable components
- scss (for styled components)
- react-helment (for seo)
- Other Packages (All packages present in FormController/index.js)
## File structure of the new project
```tree
src/components/
|
|---
src/pages/
|
|---FormBuilder
|
|---form-builder.scss
|---index.jsx
|---components
|----FormController/ //will be entirely copied from the datoms_react_components project
| |-index.js
| |-style.scss
| |-DefaultConfigs.js
|
|--FormComponentsMenu.jsx
|--AccesibilityMenu.jsx
```
## FormBuilder.jsx
- The UI will have 3 different parts
- Form Components Menu (its code will be present in FormComponentsMenu.jsx)
- A "middle area" for viewing the form. (its code will be present in FormBuilder.jsx only)
- Accesibility Menu (its code will be present in AccesibilityMenu.jsx)
- It will have two child components:- FormComponentsMenu.jsx & AccesibilityMenu.jsx
- the "middle area" will render FormController compononent.
```jsx
<FormController json={json} onCallback={onCallback} />
// onCallback is function.
const onCallback = (err, values) => {
if (err) {
console.log('onCallback: Error');
console.log(err);
} else {
console.log('onCallback: Success');
console.log(values);
}
};
// the variable json is defined below. Its a useState hook.
```
- It will use a useState hook named **json** to store the json that is responsible to render the whole form in the middle area
- Whenever the JSON is modified by putting new components in the "middle-area" or by manipulating any one component, the whole FormBuilder component will be re-rendered to show the new UI obtained from that new modified JSON.
- initialValue of **json** variable (useState hook) will be
```json
json = {
Form: {
compo: 'Form',
state: {
type: 'student',
},
props: {
name: 'basic',
initialValues: { remember: true },
onFinish: "(values) => { console.log('Success:', values); }",
onFinishFailed:
"(errorInfo) => { console.log('Failed:', errorInfo); }",
onValuesChange:
'(changedFields, allFields) => { console.log(changedFields); console.log(this.state); if (changedFields.type){ this.setState({type:changedFields.type}); this.formRef.current.setFieldsValue({grade:""})} }',
onFieldsChange:
'(changedFields, allFields) => { console.log("onFieldsChange Params:",changedFields, allFields); console.log("onFieldsChange"); }',
labelCol: {
span: 8,
},
wrapperCol: {
span: 16,
},
},
child: {
}
}
}
```
**Main Aim**
- The **json** variable will be modified everytime by the user that will cause the re-render to happen everytime.
- for example:
- Upon placing a new form component, the component's json will be added to **json** variable.
- When a new component is placed or any component is selected, the Accessibilty Menu will show the Props of that component and that props can be changed by the user from that Accessibility Menu UI. When any change is made from the Accessibilty menu, the json is again modified, thus causing a re-render.
**Selecting a form component**
```js
// get all form components
let formItems = document.querySelectorAll('.ant-form-item');
// search and get that clicked form component
formItems.forEach(formItem => {
formItem.addEventListener('click', (event)=>{
let selectedNode = event.target
while(selectedNode !== formItem){
selectedNode = selectedNode.parentNode
}
if(formItem === selectedNode){
let index = Array.from(formItems).indexOf(formItem)
console.log('index of selected component: ', index + 1);
}
})
})
```
**Adding/Deleting/Modifying a form components**
- In FormBuilder.jsx, there will be two different functions to add and delete a form component.
- Adding a component
- When a component is placed/added, assigning the key of this form component is the main priority. The key is basically looks like "Item1", "Item2", etc
- in the name "Item1", "1" is the index.
- when this child components is added to the form at a specific position, say, the fourth position from the top, then, its key's name must be Item4.
- All the existing key with index <= 4 :- "Item4", "Item5", "Item6", so on... will have a increment of 1 in thier index
- Item4 -> Item5, Item5 -> Item6, Item6-> Item7 and then, the new Item4 is appended in the JSON's child object.
- JSON is always sorted wrt keys of the children key-value pairs. So, Item4 will always be present in the 4 position of the child object in the JSON.
- Deleting a component
- When a component is removed/deleted, the JSON for that deleted child component is removed and the indexes of the components that have greater index value will have a decrement of 1 in their index
- Lets say the form component at 4th position fro top is to be removed,
- The Item4 is discarded from the child object in the JSON.
- existing keys with index > 4 will have a decrement in their indexes. i.e., Item5 -> Item4, Item6 -> Item5, Item7-> Item6
- Modifying a component's props.
- Using the Accessibily menu, the props of the selected component can be modified
## FormComponentsMenu.jsx
It will contain all form Components that can be drag dropped to the middle-area
## AccessibilityMenu.jsx
To generate the modifiers or Knobs UI, the **props object** will be rendered in a specific meainingful way
for example consider the props object:-
```
props: {
id: this,
label: 'Username',
name: 'username',
rules: [
{
required: true,
message: 'Please input your username!',
},
],
}
```
here, the Knobs UI for the direct childrem of props object will be rendered in a different way
And
the Knobs UI for the rules Array will be rendered in a different way
----------------------------------
## Test Cases
1. Placing an form Component.
- Simply drag and drop a form component from component sidebar to the middle area
2. Removing a form Component.
- Hover on the form component and when the delete icon appears on the component, click on that icon to delete component
3. Repositioning a form Component.
- Drag and shift the component upwards or downwards to reposition it
4. Modifying the component's props.
- click on a placed form component. on the right hand side accessibility menu modify the props to change the component's props.