--- tags: gy --- # Ilims custom form groups Goal is to be able to group properties together in an object. Some of that object's properties are not shown to the user by default. This can easily be generalized to create arrays of objects. ## Custom form format Currently the custom form format has a `forms` field and a `fields` field. This would add a new `groups` field: ```js= { groups: [{ id: 'group1-uuid', name: 'group1', label: 'Group 1', fields: ["field1-uuid", "field2-uuid"], multiple: true }], fields: [{ id: 'field1-uuid', label: 'Field 1', name: 'field1', // ... }, { id: 'field-uuid-2', label: 'Field 2', name: 'field2', // ... }] } ``` If group 1 is used in a form with `multiple: false` it creates an object with the following structure: ```js= { group1: { field1: '1', field2: '2', } } ``` otherwise `group1` is an array ```js= { group1: [{ field1: '1-1', field2: '1-2' }] } ``` Groups can only reference fields, not other groups. The multiple property is immutable to prevent data values to switch between being objects and arrays. In the `forms` property, groups are defined along fields ```js= [{ id: 'form-1-uuid', layout: { title: 'Form title', nColumns: 3, sections: [{ id: 'section1-uuid', name: 'Section 1', rows: [{ id: 'row1-uuid', group: { // This new property is optional groupId: 'group1', // Dynamic means optional properties in objects can be added / removed dynamically // we only render required fields by default // Other possible values: "static" type: 'dynamic', } columns: [{ fieldId: 'field1-uuid', colSpan: 1, required: true, }] }] }] } }] ``` Groups are rows so they cannot be mixed with other fields or other groups in the same row. Groups with many fields can span over multiple rows (they wrap) in the form but are defined as a single row in the form object. ## Create groups Creating groups will just be selecting a list of fields, setting the multiple preference. There will be a preview of the group as for regular fields. ## Editing groups It's possible to add new fields after they have been created. It's not possible to remove fields so that they do not appear anymore in forms, but it's possible to make them optional in the form. The group name is immutable as for fields to prevent changes in the data structure. ## Rendering the groups in a form There should be a visual cue that fields are related via a group. The order in which properties are shown is: mandatory properties first, then in order in which user has added them for dynamic fields. When page is reloaded all optional properties are in the same order as in the group definition. In a dynamic group, optional fields are not shown by default. They users opts in displaying them and can remove them afterwards. When updating, optional fields with an initial value should be shown. ## Configuring groups in a form layout All fields in a group are shown even when they are optional and "dynamic". Before saving to the database, it is ensured that all columns of the group are defined. It's not possible to remove a single column in the form if it's in a group. When trying to do so the user is prompted to remove the whole group from the form. When editing a field which is within a group , it's not possible to change the field, but it's possible to change how many columns it should span. In group, fields have less constraints in the number of cols they can span it only has to be maximum the total number of columns. Group fields also have other different options when they are hovered (edit, minimize -> colspan = 1, maximize -> colspan = maxCol) ## Finding groups It's possible to switch between a group tab and a field tab from the page which currently show the list of fields. ## Known limitations Arrays have to be objects, it's not possible to create an array of strings or numbers in a custom form. This is also a limitation of react-hook-forms so removing this constraint would not play nice with the library. ## Other technical aspects The dynamic option should enable a mode in RHF which is called `shouldUnregister`. The mode removes fields from the form result when they are unmounted and default values are not merged to the end result. The mode is yet unsupported in @zakodium/components, and the first step would be to experiment with it.