Skip to content

Commit acce4cd

Browse files
committed
feat: inject custom-control-wrapper in controlWrapper vue vanilla to replace the default controlWrapper
1 parent 5c6806f commit acce4cd

File tree

7 files changed

+149
-3
lines changed

7 files changed

+149
-3
lines changed

packages/vue-vanilla/src/controls/ControlWrapper.vue

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
<template>
2-
<div v-if="visible" :id="id" :class="styles.control.root">
2+
<component
3+
:is="customControlWrapper.component"
4+
v-bind="customControlWrapper.props"
5+
v-if="visible && customControlWrapper && customControlWrapper.component"
6+
>
7+
<slot></slot>
8+
</component>
9+
10+
<div v-else-if="visible" :id="id" :class="styles.control.root">
311
<label :for="id + '-input'" :class="styles.control.label">
412
{{ computedLabel }}
513
</label>
@@ -14,9 +22,9 @@
1422

1523
<script lang="ts">
1624
import { isDescriptionHidden, computeLabel } from '@jsonforms/core';
17-
import { defineComponent, PropType } from 'vue';
25+
import { defineComponent, inject, PropType } from 'vue';
1826
import { Styles } from '../styles';
19-
import { Options } from '../util';
27+
import { type CustomControllWrapper, Options } from '../util';
2028
2129
export default defineComponent({
2230
name: 'ControlWrapper',
@@ -65,6 +73,17 @@ export default defineComponent({
6573
type: Object as PropType<Styles>,
6674
},
6775
},
76+
setup(props: any) {
77+
const customControlWrapper = inject<CustomControllWrapper | undefined>(
78+
'custom-control-wrapper',
79+
undefined
80+
);
81+
if (customControlWrapper?.component) {
82+
customControlWrapper.props = { ...props, ...customControlWrapper?.props };
83+
}
84+
85+
return { customControlWrapper };
86+
},
6887
computed: {
6988
showDescription(): boolean {
7089
return !isDescriptionHidden(
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import type { Component } from 'vue';
2+
3+
export interface CustomControllWrapper {
4+
component: Component;
5+
props?: Record<string, any>;
6+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
export * from './options';
22
export * from './composition';
3+
export * from './customControlWrapper';
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { expect } from 'chai';
2+
import { mountJsonFormsWithCustomControlWrapper } from '../util';
3+
4+
const schema = {
5+
type: 'string',
6+
};
7+
const uischema = {
8+
type: 'Control',
9+
scope: '#',
10+
};
11+
12+
describe('CustomControlWrapper.vue', () => {
13+
it('renders a custom control wrapper', () => {
14+
const wrapper = mountJsonFormsWithCustomControlWrapper(
15+
'',
16+
schema,
17+
uischema
18+
);
19+
expect(wrapper.find('.customWrapper').exists()).to.be.true;
20+
});
21+
});
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<template>
2+
<div v-if="visible" :id="id" class="customWrapper">
3+
{{ label }}: <slot></slot>
4+
</div>
5+
</template>
6+
7+
<script lang="ts">
8+
import { defineComponent } from 'vue';
9+
10+
export default defineComponent({
11+
name: 'CustomControlWrapper',
12+
props: {
13+
id: {
14+
required: true,
15+
type: String,
16+
},
17+
description: {
18+
required: false as const,
19+
type: String,
20+
default: undefined,
21+
},
22+
errors: {
23+
required: false as const,
24+
type: String,
25+
default: undefined,
26+
},
27+
label: {
28+
required: false as const,
29+
type: String,
30+
default: undefined,
31+
},
32+
appliedOptions: {
33+
required: false as const,
34+
type: Object,
35+
default: undefined,
36+
},
37+
visible: {
38+
required: false as const,
39+
type: Boolean,
40+
default: true,
41+
},
42+
required: {
43+
required: false as const,
44+
type: Boolean,
45+
default: false,
46+
},
47+
isFocused: {
48+
required: false as const,
49+
type: Boolean,
50+
default: false,
51+
},
52+
styles: {
53+
required: true,
54+
type: Object,
55+
},
56+
},
57+
});
58+
</script>
59+
60+
61+
<style scoped>
62+
.customWrapper {
63+
display: flex;
64+
}
65+
</style>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<script lang="ts">
2+
import { defineComponent } from 'vue';
3+
// eslint-disable-next-line vue/no-unused-components
4+
import CustomControlWrapper from './CustomControlWrapper.vue';
5+
import TestComponent from './TestComponent.vue';
6+
7+
export default defineComponent({
8+
name: 'TestComponentWithCustomWrapper',
9+
components: {
10+
TestComponent,
11+
},
12+
provide() {
13+
return {
14+
'custom-control-wrapper': { component: CustomControlWrapper },
15+
};
16+
},
17+
});
18+
</script>
19+
20+
<template>
21+
<TestComponent />
22+
</template>

packages/vue-vanilla/tests/unit/util/util.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { mount } from '@vue/test-utils';
22
import TestComponent from './TestComponent.vue';
3+
import TestComponentWithCustomControlWrapper from './TestComponentWithCustomControlWrapper.vue';
34

45
export const mountJsonForms = (
56
data: any,
@@ -11,3 +12,14 @@ export const mountJsonForms = (
1112
props: { initialData: data, schema, uischema, config },
1213
});
1314
};
15+
16+
export const mountJsonFormsWithCustomControlWrapper = (
17+
data: any,
18+
schema: any,
19+
uischema?: any,
20+
config?: any
21+
) => {
22+
return mount(TestComponentWithCustomControlWrapper, {
23+
props: { initialData: data, schema, uischema, config },
24+
});
25+
};

0 commit comments

Comments
 (0)