Skip to content

Commit f4e490e

Browse files
committed
allow webcomponent to use properties
1 parent 901def6 commit f4e490e

File tree

13 files changed

+540
-1034
lines changed

13 files changed

+540
-1034
lines changed

packages/example/src/components/VuetifyJsonFormsWrapper.vue

Lines changed: 61 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,68 @@
1-
<script setup lang="ts">
2-
import { ref, useAttrs } from 'vue';
1+
<script lang="ts">
2+
import { defineComponent, ref, h, useAttrs, watch, nextTick } from 'vue';
3+
import { VProgressLinear } from 'vuetify/components';
34
import { useScriptTag } from '@vueuse/core';
45
5-
const location = './js/vuetify-json-forms.js';
6-
const loading = ref(true);
6+
export default defineComponent({
7+
name: 'VuetifyJsonFormsWrapper',
8+
components: { VProgressLinear },
9+
setup(_, { slots }) {
10+
const attrs = useAttrs(); // collect all props/attrs
11+
const loading = ref(true);
12+
const elRef = ref<HTMLElement | null>(null);
713
8-
// Disable automatic inheritance of attributes
9-
defineOptions({
10-
inheritAttrs: false,
11-
});
14+
// Helper: assign props to the web component only if they differ
15+
const assignProps = (el: HTMLElement, props: Record<string, any>) => {
16+
Object.entries(props).forEach(([key, value]) => {
17+
if ((el as any)[key] !== value) (el as any)[key] = value;
18+
});
19+
};
20+
21+
// Load the web component dynamically using useScriptTag
22+
useScriptTag(
23+
'./js/vuetify-json-forms.js',
24+
async () => {
25+
loading.value = false;
26+
27+
// Wait for DOM update to ensure the web component is mounted
28+
await nextTick();
29+
30+
if (elRef.value) {
31+
assignProps(elRef.value, attrs);
32+
}
33+
},
34+
{ type: 'module' },
35+
);
1236
13-
// Get $attrs manually
14-
const attrs = useAttrs();
37+
// Watch for prop changes and update the web component dynamically
38+
watch(
39+
() => ({ ...attrs }),
40+
(newAttrs) => {
41+
if (!elRef.value) return;
42+
assignProps(elRef.value, newAttrs);
43+
},
44+
{ deep: true },
45+
);
1546
16-
useScriptTag(
17-
location,
18-
// on script tag loaded.
19-
(_el: HTMLScriptElement) => {
20-
loading.value = false;
47+
return () => {
48+
if (loading.value) {
49+
return h(VProgressLinear, {
50+
indeterminate: true,
51+
rounded: true,
52+
height: 6,
53+
});
54+
}
55+
56+
return h(
57+
'vuetify-json-forms',
58+
{ ref: elRef },
59+
Object.keys(slots).length
60+
? Object.fromEntries(
61+
Object.entries(slots).map(([name, slotFn]) => [name, slotFn]),
62+
)
63+
: undefined,
64+
);
65+
};
2166
},
22-
{ type: 'module' },
23-
);
67+
});
2468
</script>
25-
26-
<template>
27-
<v-progress-linear
28-
v-if="loading"
29-
indeterminate
30-
rounded
31-
height="6"
32-
></v-progress-linear>
33-
<vuetify-json-forms v-else v-bind="attrs"></vuetify-json-forms>
34-
</template>

packages/example/src/core/types.ts

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
import type { ActionEvent } from '@chobantonov/jsonforms-vuetify-renderers';
22
import type {
3-
JsonFormsCellRendererRegistryEntry,
4-
JsonFormsRendererRegistryEntry,
53
JsonFormsUISchemaRegistryEntry,
64
JsonSchema,
75
UISchemaElement,
86
} from '@jsonforms/core';
7+
import type { StateProps } from '@jsonforms/examples';
98

109
export type ExampleDescription = {
1110
name: string;
@@ -20,19 +19,7 @@ export type ExampleInputDescription = {
2019
uischemas?: JsonFormsUISchemaRegistryEntry[];
2120
data?: any;
2221
i18n?: Record<string, any>;
23-
renderers?: JsonFormsRendererRegistryEntry[];
24-
actions?: { label: string; apply: (props: StateProps) => any }[];
22+
actions?: { label: string; apply: (props: StateProps) => StateProps }[];
2523
onHandleAction?: (event: ActionEvent) => void;
2624
config?: Record<string, any>;
2725
};
28-
29-
export interface StateProps {
30-
data: any;
31-
schema?: JsonSchema;
32-
uischema?: UISchemaElement;
33-
renderers: JsonFormsRendererRegistryEntry[];
34-
cells?: JsonFormsCellRendererRegistryEntry[];
35-
config?: any;
36-
uischemas?: JsonFormsUISchemaRegistryEntry[];
37-
readonly?: boolean;
38-
}

packages/example/src/examples/custom-renderer/CustomArrayRenderer.vue

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,21 @@
11
<template>
22
<array-layout-renderer v-bind="$props">
3-
<template v-slot:toolbar-elements>{{ null }}</template>
4-
<template v-slot:actions="actionsProps">
3+
<template v-slot:toolbar-elements="actionsProps">
54
<v-tooltip bottom>
65
<template v-slot:activator="{ props }">
76
<v-btn
87
color="primary"
98
rounded
10-
:aria-label="actionsProps.labels.add"
9+
:aria-label="actionsProps.control.translations.addAriaLabel"
1110
v-bind="props"
1211
:class="actionsProps.styles.arrayList.addButton"
1312
:disabled="actionsProps.addDisabled"
1413
@click="actionsProps.addClick"
1514
>
16-
<v-icon>$plus</v-icon> {{ actionsProps.labels.add }}
15+
Custom Add
1716
</v-btn>
1817
</template>
19-
{{ actionsProps.labels.add }}
18+
{{ actionsProps.control.translations.addTooltip }}
2019
</v-tooltip>
2120
</template>
2221
</array-layout-renderer>

packages/example/src/examples/custom-renderer/index.ts

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,42 @@ import { entry as customArrayRendererEntry } from './CustomArrayRenderer.vue';
44
import data from './data.json';
55
import schema from './schema.json';
66
import uischema from './uischema.json';
7+
import type { StateProps } from '@jsonforms/examples';
8+
9+
const actions = [
10+
{
11+
label: 'Register Custom Renderer',
12+
apply: (props: StateProps) => {
13+
const alreadyRegistered = props.renderers.some(
14+
(r) => r === customArrayRendererEntry,
15+
);
16+
17+
return {
18+
...props,
19+
renderers: alreadyRegistered
20+
? props.renderers
21+
: [...props.renderers, customArrayRendererEntry],
22+
};
23+
},
24+
},
25+
{
26+
label: 'Deregister Custom Renderer',
27+
apply: (props: StateProps) => {
28+
return {
29+
...props,
30+
renderers: [
31+
...props.renderers.filter((r) => r !== customArrayRendererEntry),
32+
],
33+
};
34+
},
35+
},
36+
];
737

838
export const input: ExampleInputDescription = {
939
schema,
1040
uischema,
1141
data,
12-
renderers: [customArrayRendererEntry],
42+
actions,
1343
};
1444

1545
registerExamples([

packages/example/src/examples/multi-enum/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export const input: ExampleInputDescription = { schema, uischema, data };
88

99
registerExamples([
1010
{
11-
name: 'multi-array',
11+
name: 'multi-enum',
1212
label: 'Multi Enum',
1313
input,
1414
},

0 commit comments

Comments
 (0)