1+ <template >
2+ <div v-if =" control.visible" >
3+ <combinator-properties
4+ :schema =" control.schema"
5+ combinator-keyword =" oneOf"
6+ :path =" path"
7+ />
8+
9+ <control-wrapper
10+ v-bind =" controlWrapper"
11+ :styles =" styles"
12+ :is-focused =" isFocused"
13+ :applied-options =" appliedOptions"
14+ >
15+ <select
16+ :id =" control.id + '-input'"
17+ :class =" styles.control.select"
18+ :value =" selectIndex"
19+ :disabled =" !control.enabled"
20+ :autofocus =" appliedOptions.focus"
21+ @change =" handleSelectChange"
22+ @focus =" isFocused = true"
23+ @blur =" isFocused = false"
24+ >
25+ <option
26+ v-for =" optionElement in indexedOneOfRenderInfos"
27+ :key =" optionElement.index"
28+ :value =" optionElement.index"
29+ :label =" optionElement.label"
30+ :class =" styles.control.option"
31+ ></option >
32+ </select >
33+ </control-wrapper >
34+
35+ <dispatch-renderer
36+ v-if =" selectedIndex !== undefined && selectedIndex !== null"
37+ :schema =" indexedOneOfRenderInfos[selectedIndex].schema"
38+ :uischema =" indexedOneOfRenderInfos[selectedIndex].uischema"
39+ :path =" control.path"
40+ :renderers =" control.renderers"
41+ :cells =" control.cells"
42+ :enabled =" control.enabled"
43+ />
44+
45+ <dialog ref =" dialog" :class =" styles.dialog.root" >
46+ <h1 :class =" styles.dialog.title" >
47+ {{ control.translations.clearDialogTitle }}
48+ </h1 >
49+
50+ <p :class =" styles.dialog.body" >
51+ {{ control.translations.clearDialogMessage }}
52+ </p >
53+
54+ <div :class =" styles.dialog.actions" >
55+ <button :onclick =" onCancel" :class =" styles.dialog.buttonSecondary" >
56+ {{ control.translations.clearDialogDecline }}
57+ </button >
58+ <button
59+ ref =" confirm"
60+ :onclick =" onConfirm"
61+ :class =" styles.dialog.buttonPrimary"
62+ >
63+ {{ control.translations.clearDialogAccept }}
64+ </button >
65+ </div >
66+ </dialog >
67+ </div >
68+ </template >
69+
70+ <script lang="ts">
71+ import {
72+ CombinatorSubSchemaRenderInfo ,
73+ ControlElement ,
74+ createCombinatorRenderInfos ,
75+ createDefaultValue ,
76+ isOneOfControl ,
77+ JsonFormsRendererRegistryEntry ,
78+ rankWith ,
79+ } from ' @jsonforms/core' ;
80+ import {
81+ DispatchRenderer ,
82+ rendererProps ,
83+ RendererProps ,
84+ useJsonFormsOneOfControl ,
85+ } from ' @jsonforms/vue' ;
86+ import isEmpty from ' lodash/isEmpty' ;
87+ import { defineComponent , nextTick , ref } from ' vue' ;
88+ import { useVanillaControl } from ' ../util' ;
89+ import { ControlWrapper } from ' ../controls' ;
90+ import CombinatorProperties from ' ./components/CombinatorProperties.vue' ;
91+
92+ const controlRenderer = defineComponent ({
93+ name: ' OneOfRenderer' ,
94+ components: {
95+ ControlWrapper ,
96+ DispatchRenderer ,
97+ CombinatorProperties ,
98+ },
99+ props: {
100+ ... rendererProps <ControlElement >(),
101+ },
102+ setup(props : RendererProps <ControlElement >) {
103+ const input = useJsonFormsOneOfControl (props );
104+ const control = input .control .value ;
105+
106+ const selectedIndex = ref (control .indexOfFittingSchema );
107+ const selectIndex = ref (selectedIndex .value );
108+ const newSelectedIndex = ref (0 );
109+
110+ const dialog = ref <HTMLDialogElement >();
111+ const confirm = ref <HTMLElement >();
112+
113+ return {
114+ ... useVanillaControl (input ),
115+ selectedIndex ,
116+ selectIndex ,
117+ newSelectedIndex ,
118+ dialog ,
119+ confirm ,
120+ };
121+ },
122+ computed: {
123+ indexedOneOfRenderInfos(): (CombinatorSubSchemaRenderInfo & {
124+ index: number ;
125+ })[] {
126+ const result = createCombinatorRenderInfos (
127+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
128+ this .control .schema .oneOf ! ,
129+ this .control .rootSchema ,
130+ ' oneOf' ,
131+ this .control .uischema ,
132+ this .control .path ,
133+ this .control .uischemas
134+ );
135+
136+ return result
137+ .filter ((info ) => info .uischema )
138+ .map ((info , index ) => ({ ... info , index: index }));
139+ },
140+ },
141+ methods: {
142+ handleSelectChange(event : Event ): void {
143+ const target = event .target as any ;
144+ this .selectIndex = target .value ;
145+
146+ if (this .control .enabled && ! isEmpty (this .control .data )) {
147+ this .showDialog ();
148+ nextTick (() => {
149+ this .newSelectedIndex = this .selectIndex ;
150+ // revert the selection while the dialog is open
151+ this .selectIndex = this .selectedIndex ;
152+ this .confirm ?.focus ();
153+ });
154+ } else {
155+ nextTick (() => {
156+ this .selectedIndex = this .selectIndex ;
157+ });
158+ }
159+ },
160+ showDialog(): void {
161+ this .dialog ?.showModal ();
162+ },
163+ closeDialog(): void {
164+ this .dialog ?.close ();
165+ },
166+ onConfirm(): void {
167+ this .newSelection ();
168+ this .closeDialog ();
169+ },
170+ onCancel(): void {
171+ this .newSelectedIndex = this .selectedIndex ;
172+ this .closeDialog ();
173+ },
174+ newSelection(): void {
175+ this .handleChange (
176+ this .control .path ,
177+ this .newSelectedIndex !== undefined && this .newSelectedIndex !== null
178+ ? createDefaultValue (
179+ this .indexedOneOfRenderInfos [this .newSelectedIndex ].schema
180+ )
181+ : {}
182+ );
183+ this .selectIndex = this .newSelectedIndex ;
184+ this .selectedIndex = this .newSelectedIndex ;
185+ },
186+ },
187+ });
188+
189+ export default controlRenderer ;
190+
191+ export const entry: JsonFormsRendererRegistryEntry = {
192+ renderer: controlRenderer ,
193+ tester: rankWith (3 , isOneOfControl ),
194+ };
195+ </script >
196+
0 commit comments