Skip to content

Commit 369370a

Browse files
authored
feat: support maxItems & minItems in Vue array renderer
Disable add and remove buttons in Vue array renderer according to 'maxItems' and 'minItems' when the 'restrict' UI Schema option is set. Also all array buttons are now disabled if the overall control is disabled.
1 parent f74e9ed commit 369370a

File tree

5 files changed

+66
-2
lines changed

5 files changed

+66
-2
lines changed

packages/examples/src/examples/arrays-with-detail.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ export const schema = {
3232
occupation: { type: 'string' },
3333
comments: {
3434
type: 'array',
35+
minItems: 2,
36+
maxItems: 8,
3537
items: {
3638
type: 'object',
3739
properties: {
@@ -58,6 +60,7 @@ export const uischema = {
5860
scope: '#/properties/comments',
5961
options: {
6062
showSortButtons: true,
63+
restrict: true,
6164
detail: {
6265
type: 'VerticalLayout',
6366
elements: [

packages/examples/src/examples/arrays-with-sorting.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ export const schema = {
3030
properties: {
3131
comments: {
3232
type: 'array',
33+
minItems: 2,
34+
maxItems: 8,
3335
items: {
3436
type: 'object',
3537
properties: {
@@ -64,6 +66,7 @@ export const uischema = {
6466
scope: '#/properties/comments',
6567
options: {
6668
showSortButtons: true,
69+
restrict: true,
6770
},
6871
},
6972
],
@@ -81,6 +84,7 @@ export const uischemaWithSorting = {
8184
scope: '#/properties/comments',
8285
options: {
8386
showSortButtons: true,
87+
restrict: true,
8488
},
8589
},
8690
],

packages/vue/vue-vanilla/src/array/ArrayListElement.vue

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
2020
</button>
2121
<button
22+
:disabled="!deleteEnabled"
2223
:class="styles.arrayList.itemDelete"
2324
type="button"
2425
@click="deleteClicked"
@@ -69,6 +70,11 @@ const listItem = defineComponent({
6970
type: Function,
7071
default: undefined,
7172
},
73+
deleteEnabled: {
74+
required: false,
75+
type: Boolean,
76+
default: true,
77+
},
7278
delete: {
7379
required: false,
7480
type: Function,

packages/vue/vue-vanilla/src/array/ArrayListRenderer.vue

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
<button
55
:class="styles.arrayList.addButton"
66
type="button"
7+
:disabled="
8+
!control.enabled || (appliedOptions.restrict && maxItemsReached)
9+
"
710
@click="addButtonClick"
811
>
912
+
@@ -19,9 +22,10 @@
1922
>
2023
<array-list-element
2124
:move-up="moveUp(control.path, index)"
22-
:move-up-enabled="index > 0"
25+
:move-up-enabled="control.enabled && index > 0"
2326
:move-down="moveDown(control.path, index)"
24-
:move-down-enabled="index < control.data.length - 1"
27+
:move-down-enabled="control.enabled && index < control.data.length - 1"
28+
:delete-enabled="control.enabled && !minItemsReached"
2529
:delete="removeItems(control.path, [index])"
2630
:label="childLabelForIndex(index)"
2731
:styles="styles"
@@ -50,6 +54,8 @@ import {
5054
rankWith,
5155
ControlElement,
5256
schemaTypeIs,
57+
Resolve,
58+
JsonSchema,
5359
} from '@jsonforms/core';
5460
import { defineComponent } from 'vue';
5561
import {
@@ -77,6 +83,29 @@ const controlRenderer = defineComponent({
7783
noData(): boolean {
7884
return !this.control.data || this.control.data.length === 0;
7985
},
86+
arraySchema(): JsonSchema | undefined {
87+
return Resolve.schema(
88+
this.schema,
89+
this.control.uischema.scope,
90+
this.control.rootSchema
91+
);
92+
},
93+
maxItemsReached(): boolean | undefined {
94+
return (
95+
this.arraySchema !== undefined &&
96+
this.arraySchema.maxItems !== undefined &&
97+
this.control.data !== undefined &&
98+
this.control.data.length >= this.arraySchema.maxItems
99+
);
100+
},
101+
minItemsReached(): boolean | undefined {
102+
return (
103+
this.arraySchema !== undefined &&
104+
this.arraySchema.minItems !== undefined &&
105+
this.control.data !== undefined &&
106+
this.control.data.length <= this.arraySchema.minItems
107+
);
108+
},
80109
},
81110
methods: {
82111
composePaths,

packages/vue/vue-vanilla/tests/unit/array/ArrayListRenderer.spec.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,18 @@ import { mountJsonForms } from '../util';
44
const schema = {
55
type: 'array',
66
title: 'My Array',
7+
maxItems: 3,
8+
minItems: 1,
79
items: {
810
type: 'string',
911
},
1012
};
1113
const uischema = {
1214
type: 'Control',
1315
scope: '#',
16+
options: {
17+
restrict: true,
18+
},
1419
};
1520

1621
describe('ArrayListRenderer.vue', () => {
@@ -37,13 +42,30 @@ describe('ArrayListRenderer.vue', () => {
3742
expect(wrapper.vm.data).to.deep.equal(['a', 'b', '']);
3843
});
3944

45+
it('add button disabled if maxItems is reached', async () => {
46+
const wrapper = mountJsonForms(['a', 'b'], schema, uischema);
47+
const addButton = wrapper.find('.array-list-add');
48+
expect(addButton.attributes().disabled).to.not.exist;
49+
await addButton.trigger('click');
50+
expect(addButton.attributes().disabled).to.exist;
51+
});
52+
4053
it('remove element from array', async () => {
4154
const wrapper = mountJsonForms(['a', 'b', 'c'], schema, uischema);
4255
const deleteButtons = wrapper.findAll('.array-list-item-delete');
4356
await deleteButtons[1].trigger('click');
4457
expect(wrapper.vm.data).to.deep.equal(['a', 'c']);
4558
});
4659

60+
it('remove button disabled if minItems is reached', async () => {
61+
const wrapper = mountJsonForms(['a', 'b'], schema, uischema);
62+
const deleteButtons = wrapper.findAll('.array-list-item-delete');
63+
expect(deleteButtons[0].attributes().disabled).to.not.exist;
64+
expect(deleteButtons[1].attributes().disabled).to.not.exist;
65+
await deleteButtons[0].trigger('click');
66+
expect(deleteButtons[0].attributes().disabled).to.exist;
67+
});
68+
4769
it('move element up', async () => {
4870
const wrapper = mountJsonForms(['a', 'b', 'c'], schema, uischema);
4971
const moveUpButtons = wrapper.findAll('.array-list-item-move-up');

0 commit comments

Comments
 (0)