Skip to content

Commit 03bfec6

Browse files
authored
Merge pull request #92 from headwirecom/feature/array-add-button-position
Add some options for the Add Button of Table Array Control
2 parents 44ed1c5 + 701b737 commit 03bfec6

File tree

3 files changed

+126
-8
lines changed

3 files changed

+126
-8
lines changed

packages/spectrum/README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,18 @@ JSONForms eliminates the tedious task of writing fully-featured forms by hand by
77
# Spectrum Renderers Package
88

99
!!!! Work in Progress !!!
10+
11+
# Custom options
12+
13+
### Custom options for Table Array Control
14+
```js
15+
{
16+
"type": "Control",
17+
"scope": "#/properties/myArray",
18+
"options": {
19+
"addButtonPosition": "top", // "top" or "bottom"
20+
"addButtonLabel": "Add item", // optional custom label for Add button
21+
"addButtonLabelType": "tooltip" // "tooltip" or "inline"
22+
}
23+
}
24+
```

packages/spectrum/src/complex/SpectrumTableArrayControl.tsx

Lines changed: 54 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,17 @@ class SpectrumTableArrayControl extends React.Component<
144144
)(schema.properties)
145145
: [<Column key='items'>Items</Column>];
146146

147+
const uioptions: UIOptions = {
148+
addButtonPosition:
149+
uischema.options?.addButtonPosition === 'bottom' ? 'bottom' : 'top',
150+
addButtonLabel:
151+
uischema.options?.addButtonLabel || `Add to ${labelObject.text}`,
152+
addButtonLabelType:
153+
uischema.options?.addButtonLabelType === 'inline'
154+
? 'inline'
155+
: 'tooltip',
156+
};
157+
147158
return (
148159
<View
149160
UNSAFE_className='spectrum-table-array-control'
@@ -160,15 +171,12 @@ class SpectrumTableArrayControl extends React.Component<
160171
<View isHidden={allErrorsMessages.length === 0} marginEnd='auto'>
161172
<ErrorIndicator errors={allErrorsMessages} />
162173
</View>
163-
<TooltipTrigger delay={0}>
164-
<ActionButton
165-
UNSAFE_className='add-button'
174+
{uioptions.addButtonPosition === 'top' && (
175+
<AddButton
176+
{...uioptions}
166177
onPress={addItem(path, createDefaultValue(schema))}
167-
>
168-
<Add />
169-
</ActionButton>
170-
<Tooltip>Add to {labelObject.text}</Tooltip>
171-
</TooltipTrigger>
178+
/>
179+
)}
172180
</Flex>
173181
</Header>
174182

@@ -286,9 +294,47 @@ class SpectrumTableArrayControl extends React.Component<
286294
)}
287295
</TableBody>
288296
</Table>
297+
298+
{uioptions.addButtonPosition === 'bottom' && (
299+
<View paddingTop='size-125'>
300+
<AddButton
301+
{...uioptions}
302+
onPress={addItem(path, createDefaultValue(schema))}
303+
/>
304+
</View>
305+
)}
289306
</View>
290307
);
291308
}
292309
}
293310

294311
export default withJsonFormsArrayControlProps(SpectrumTableArrayControl);
312+
313+
function AddButton(
314+
props: Pick<UIOptions, 'addButtonLabel' | 'addButtonLabelType'> & {
315+
onPress: () => void;
316+
}
317+
) {
318+
const { addButtonLabel, addButtonLabelType, onPress } = props;
319+
const button = (
320+
<ActionButton UNSAFE_className='add-button' onPress={onPress}>
321+
<Add />
322+
{addButtonLabelType === 'inline' && <Text>{addButtonLabel}</Text>}
323+
</ActionButton>
324+
);
325+
326+
return addButtonLabelType === 'tooltip' ? (
327+
<TooltipTrigger delay={0}>
328+
{button}
329+
<Tooltip>{addButtonLabel}</Tooltip>
330+
</TooltipTrigger>
331+
) : (
332+
button
333+
);
334+
}
335+
336+
interface UIOptions {
337+
addButtonPosition: 'top' | 'bottom';
338+
addButtonLabel?: string;
339+
addButtonLabelType: 'tooltip' | 'inline';
340+
}

packages/spectrum/test/renderers/SpectrumTableArrayControl.test.tsx

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,63 @@ describe('Table array control', () => {
384384
) as HTMLElement;
385385
expect(tableView.hidden).toBeFalsy();
386386
});
387+
388+
describe('uischema.options.addButtonPosition', () => {
389+
test.each([
390+
[undefined, 'top'],
391+
['top', 'top'],
392+
['bottom', 'bottom'],
393+
['foobar', 'top'],
394+
])(
395+
'when option is %s, render Add button on %s',
396+
(value: string | undefined, expectedPosition: 'top' | 'bottom') => {
397+
const { container } = renderForm(
398+
{
399+
...fixture.uischema,
400+
options: { addButtonPosition: value },
401+
},
402+
fixture.schema,
403+
fixture.data
404+
);
405+
const tablePosition = container.innerHTML.indexOf('spectrum-Table');
406+
const addButtonPosition = container.innerHTML.indexOf('add-button');
407+
if (expectedPosition === 'bottom') {
408+
expect(addButtonPosition).toBeGreaterThan(tablePosition);
409+
} else {
410+
expect(addButtonPosition).toBeLessThan(tablePosition);
411+
}
412+
}
413+
);
414+
});
415+
416+
describe('uischema.options.addButtonLabel', () => {
417+
const uischema = {
418+
...fixture.uischema,
419+
options: {
420+
addButtonLabelType: 'inline',
421+
},
422+
};
423+
test('when option is not set, should render the default label', () => {
424+
const { container } = renderForm(uischema, fixture.schema, fixture.data);
425+
expect(container.querySelector('.add-button').textContent).toBe(
426+
'Add to Test'
427+
);
428+
});
429+
430+
test('when option is set, should render it', () => {
431+
const label = 'increase the count of items';
432+
const uischemaWithLabel = {
433+
...uischema,
434+
options: { ...uischema.options, addButtonLabel: label },
435+
};
436+
const { container } = renderForm(
437+
uischemaWithLabel,
438+
fixture.schema,
439+
fixture.data
440+
);
441+
expect(container.querySelector('.add-button').textContent).toBe(label);
442+
});
443+
});
387444
});
388445

389446
describe('validations messages', () => {

0 commit comments

Comments
 (0)