Skip to content

Commit

Permalink
Merge pull request #35 from open-formulieren/feature/2-editgrid-type
Browse files Browse the repository at this point in the history
Implement types for editgrid component
  • Loading branch information
sergei-maertens authored Dec 7, 2023
2 parents d27ff07 + 0d81964 commit 6919da9
Show file tree
Hide file tree
Showing 4 changed files with 270 additions and 0 deletions.
99 changes: 99 additions & 0 deletions src/formio/components/editgrid.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import {OFValidateOptions} from 'formio/validation';

import {AnyComponentSchema, InputComponentSchema} from '..';

type Validator = 'required' | 'maxLength';
type TranslatableKeys =
| 'label'
| 'description'
| 'tooltip'
| 'groupLabel'
| 'addAnother'
| 'saveRow'
| 'removeRow';

/**
* We don't currently support these properties - they get added in by base types, so we
* need to strip them out again.
*/
type KeysToOmit =
| 'registration'
| 'placeholder'
| 'multiple'
// added by HasValidation, but currently not exposed in the form builder
| 'errors'
// added by HasValidation, but currently not exposed in the form builder
| 'translatedErrors'
| 'disabled'
| 'validateOn'
| 'showInSummary'
| 'showInEmail'
| 'showInPDF';

export type EditGridInputSchema = Omit<
InputComponentSchema<unknown, Validator, TranslatableKeys>,
'validate'
> & {
/**
* Input mode is implicitly multiple: true, so the (default) value must always have an array
* shape.
*
* We don't know what the shape inside of components is at compile time, hence the `unknown`.
*/
defaultValue?: unknown[];
// do not include the plugins validator, this behaviour is undefined
validate?: OFValidateOptions<Validator>;
};

/**
* The editgrid component schema.
*
* Edit grids ("repeating groups") are used as a blueprint for array values with complex
* nested structures (as opposed to textfield with multiple true) inside.
*
* The nested components describe a single group of fields that are repeated for every
* item. Because of that, the `defaultValue` type cannot be statically defined, as it
* is derived from the dynamic configuration.
*
* Edit grids are essentially always 'multiple: true', so this property does not apply
* to this component type either.
*
* @todo
*
* There are probably a bunch of properties used in the SDK that are not exposed in the
* form builder -> add them when we know what they are!
*
* @group Form.io components
* @category Concrete types
*/
export interface EditGridComponentSchema extends Omit<EditGridInputSchema, KeysToOmit> {
type: 'editgrid';
/**
* Nested components inside the group.
*/
components: AnyComponentSchema[];

/**
* Control whether any rows can be added or removed.
*/
disableAddingRemovingRows: boolean;
/**
* Button label to add another item.
*/
addAnother?: string;
/**
* Button label to save/confirm a single item.
*/
saveRow?: string;
/**
* Button label to remove a single item.
*/
removeRow?: string;

// custom properties

/**
* Label for an individual item, interpolated with the index of each item.
*/
groupLabel: string;
}
1 change: 1 addition & 0 deletions src/formio/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export * from './file';
export * from './radio';
export * from './addressNL';
export * from './map';
export * from './editgrid';

// Layout components
export * from './content';
Expand Down
2 changes: 2 additions & 0 deletions src/formio/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
CurrencyComponentSchema,
DateComponentSchema,
DateTimeComponentSchema,
EditGridComponentSchema,
EmailComponentSchema,
FieldsetComponentSchema,
FileComponentSchema,
Expand Down Expand Up @@ -72,6 +73,7 @@ export type AnyComponentSchema =
| AddressNLComponentSchema
| NpFamilyMembersComponentSchema
| MapComponentSchema
| EditGridComponentSchema
// layout
| ContentComponentSchema
| ColumnsComponentSchema
Expand Down
168 changes: 168 additions & 0 deletions test-d/formio/components/editgrid.test-d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
import {expectAssignable, expectNotAssignable} from 'tsd';

import {EditGridComponentSchema} from '../../../lib/';

// minimal textfield component schema
expectAssignable<EditGridComponentSchema>({
id: 'yejak',
type: 'editgrid',
key: 'someEditGrid',
label: 'Some edit grid',
components: [],
disableAddingRemovingRows: false,
groupLabel: 'Item',
});

// with nested components
expectAssignable<EditGridComponentSchema>({
id: 'yejak',
type: 'editgrid',
key: 'someEditGrid',
label: 'Some edit grid',
components: [
{
id: 'wien53il',
type: 'textfield',
key: 'nestedTextField',
label: 'Nested text field',
},
],
disableAddingRemovingRows: false,
groupLabel: 'Item',
});

// Full schema
expectAssignable<EditGridComponentSchema>({
id: 'yejak',
type: 'editgrid',
components: [],
defaultValue: [],
// basic tab in builder form
label: 'Some edit grid',
key: 'someEditGrid',
description: '',
tooltip: '',
groupLabel: 'Item',
hidden: false,
clearOnHide: true,
isSensitiveData: false,
hideLabel: false,
// display tab in builder form
disableAddingRemovingRows: false,
addAnother: '',
saveRow: '',
removeRow: '',
// validation tab in builder form
validate: {
required: false,
maxLength: 20,
},
// translations tab in builder form
openForms: {
translations: {
nl: {
label: 'foo',
description: 'bar',
tooltip: 'tooltip',
groupLabel: 'groupLabel',
addAnother: 'addAnother',
saveRow: 'saveRow',
removeRow: 'removeRow',
},
},
},
});

// different component type
expectNotAssignable<EditGridComponentSchema>({
type: 'fieldset',
} as const);

// multiple: true is implicit
expectNotAssignable<EditGridComponentSchema>({
id: 'yejak',
type: 'editgrid' as const,
key: 'someEditGrid',
label: 'Some edit grid',
components: [],
disableAddingRemovingRows: false,
groupLabel: 'Item',
multiple: false,
});

// currently we don't support plugin validators
expectNotAssignable<EditGridComponentSchema>({
id: 'yejak',
type: 'editgrid' as const,
key: 'someEditGrid',
label: 'Some edit grid',
components: [],
disableAddingRemovingRows: false,
groupLabel: 'Item',
validate: {
plugins: [],
},
});

// currently we don't support providing validation error translations
expectNotAssignable<EditGridComponentSchema>({
id: 'yejak',
type: 'editgrid' as const,
key: 'someEditGrid',
label: 'Some edit grid',
components: [],
disableAddingRemovingRows: false,
groupLabel: 'Item',
validate: {
required: true,
},
translatedErrors: {
nl: {
required: 'Je moet een waarde opgeven!!!',
},
},
});

// the 'showIn*' properties are also not (yet?) exposed
expectNotAssignable<EditGridComponentSchema>({
id: 'yejak',
type: 'editgrid' as const,
key: 'someEditGrid',
label: 'Some edit grid',
components: [],
disableAddingRemovingRows: false,
groupLabel: 'Item',
showInSummary: true,
});
expectNotAssignable<EditGridComponentSchema>({
id: 'yejak',
type: 'editgrid' as const,
key: 'someEditGrid',
label: 'Some edit grid',
components: [],
disableAddingRemovingRows: false,
groupLabel: 'Item',
showInEmail: true,
});
expectNotAssignable<EditGridComponentSchema>({
id: 'yejak',
type: 'editgrid' as const,
key: 'someEditGrid',
label: 'Some edit grid',
components: [],
disableAddingRemovingRows: false,
groupLabel: 'Item',
showInPDF: true,
});

// there's no registration configuration (yet?)
expectNotAssignable<EditGridComponentSchema>({
id: 'yejak',
type: 'editgrid' as const,
key: 'someEditGrid',
label: 'Some edit grid',
components: [],
disableAddingRemovingRows: false,
groupLabel: 'Item',
registration: {attribute: ''},
});

0 comments on commit 6919da9

Please sign in to comment.