diff --git a/packages/spectrum/README.md b/packages/spectrum/README.md
index 5021cce0..b182ed53 100644
--- a/packages/spectrum/README.md
+++ b/packages/spectrum/README.md
@@ -7,3 +7,18 @@ JSONForms eliminates the tedious task of writing fully-featured forms by hand by
# Spectrum Renderers Package
!!!! Work in Progress !!!
+
+# Custom options
+
+### Custom options for Table Array Control
+```js
+{
+ "type": "Control",
+ "scope": "#/properties/myArray",
+ "options": {
+ "addButtonPosition": "top", // "top" or "bottom"
+ "addButtonLabel": "Add item", // optional custom label for Add button
+ "addButtonLabelType": "tooltip" // "tooltip" or "inline"
+ }
+}
+```
\ No newline at end of file
diff --git a/packages/spectrum/src/complex/SpectrumTableArrayControl.tsx b/packages/spectrum/src/complex/SpectrumTableArrayControl.tsx
index 7460c8fa..0a6563f6 100644
--- a/packages/spectrum/src/complex/SpectrumTableArrayControl.tsx
+++ b/packages/spectrum/src/complex/SpectrumTableArrayControl.tsx
@@ -144,6 +144,17 @@ class SpectrumTableArrayControl extends React.Component<
)(schema.properties)
: [Items];
+ const uioptions: UIOptions = {
+ addButtonPosition:
+ uischema.options?.addButtonPosition === 'bottom' ? 'bottom' : 'top',
+ addButtonLabel:
+ uischema.options?.addButtonLabel || `Add to ${labelObject.text}`,
+ addButtonLabelType:
+ uischema.options?.addButtonLabelType === 'inline'
+ ? 'inline'
+ : 'tooltip',
+ };
+
return (
-
-
-
-
- Add to {labelObject.text}
-
+ />
+ )}
@@ -286,9 +294,47 @@ class SpectrumTableArrayControl extends React.Component<
)}
+
+ {uioptions.addButtonPosition === 'bottom' && (
+
+
+
+ )}
);
}
}
export default withJsonFormsArrayControlProps(SpectrumTableArrayControl);
+
+function AddButton(
+ props: Pick & {
+ onPress: () => void;
+ }
+) {
+ const { addButtonLabel, addButtonLabelType, onPress } = props;
+ const button = (
+
+
+ {addButtonLabelType === 'inline' && {addButtonLabel}}
+
+ );
+
+ return addButtonLabelType === 'tooltip' ? (
+
+ {button}
+ {addButtonLabel}
+
+ ) : (
+ button
+ );
+}
+
+interface UIOptions {
+ addButtonPosition: 'top' | 'bottom';
+ addButtonLabel?: string;
+ addButtonLabelType: 'tooltip' | 'inline';
+}
diff --git a/packages/spectrum/test/renderers/SpectrumTableArrayControl.test.tsx b/packages/spectrum/test/renderers/SpectrumTableArrayControl.test.tsx
index 079b2cb8..4e69df27 100644
--- a/packages/spectrum/test/renderers/SpectrumTableArrayControl.test.tsx
+++ b/packages/spectrum/test/renderers/SpectrumTableArrayControl.test.tsx
@@ -384,6 +384,63 @@ describe('Table array control', () => {
) as HTMLElement;
expect(tableView.hidden).toBeFalsy();
});
+
+ describe('uischema.options.addButtonPosition', () => {
+ test.each([
+ [undefined, 'top'],
+ ['top', 'top'],
+ ['bottom', 'bottom'],
+ ['foobar', 'top'],
+ ])(
+ 'when option is %s, render Add button on %s',
+ (value: string | undefined, expectedPosition: 'top' | 'bottom') => {
+ const { container } = renderForm(
+ {
+ ...fixture.uischema,
+ options: { addButtonPosition: value },
+ },
+ fixture.schema,
+ fixture.data
+ );
+ const tablePosition = container.innerHTML.indexOf('spectrum-Table');
+ const addButtonPosition = container.innerHTML.indexOf('add-button');
+ if (expectedPosition === 'bottom') {
+ expect(addButtonPosition).toBeGreaterThan(tablePosition);
+ } else {
+ expect(addButtonPosition).toBeLessThan(tablePosition);
+ }
+ }
+ );
+ });
+
+ describe('uischema.options.addButtonLabel', () => {
+ const uischema = {
+ ...fixture.uischema,
+ options: {
+ addButtonLabelType: 'inline',
+ },
+ };
+ test('when option is not set, should render the default label', () => {
+ const { container } = renderForm(uischema, fixture.schema, fixture.data);
+ expect(container.querySelector('.add-button').textContent).toBe(
+ 'Add to Test'
+ );
+ });
+
+ test('when option is set, should render it', () => {
+ const label = 'increase the count of items';
+ const uischemaWithLabel = {
+ ...uischema,
+ options: { ...uischema.options, addButtonLabel: label },
+ };
+ const { container } = renderForm(
+ uischemaWithLabel,
+ fixture.schema,
+ fixture.data
+ );
+ expect(container.querySelector('.add-button').textContent).toBe(label);
+ });
+ });
});
describe('validations messages', () => {