Skip to content

Commit 226b9dc

Browse files
committed
feat: Update JSON form components to handle object values correctly
The QStringControlRenderer setup function was not handling object values correctly. This commit fixes the issue by checking if the value is an object and returning its value property, or returning the value itself if it's not an object.
1 parent 81cf360 commit 226b9dc

File tree

8 files changed

+130
-61
lines changed

8 files changed

+130
-61
lines changed

src/components/genericForm/index.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ div
77
:schema="schema"
88
:uischema="uischema"
99
)
10+
//- pre(v-html="JSON.stringify(payload.target, null, 2)")
1011
</template>
1112

1213
<script lang="ts" setup>

src/components/jsonFormRenderer.vue

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
<template lang="pug">
2-
json-forms(
3-
v-if="data"
4-
:data="data"
5-
:schema="schema"
6-
:uischema="uischema"
7-
:renderers="renderers"
8-
validationMode="ValidateAndShow"
9-
:additionalErrors="getSchemaValidations"
10-
@change="onChange"
11-
)
2+
div
3+
json-forms(
4+
v-if="data"
5+
:data="data"
6+
:schema="schema"
7+
:uischema="uischema"
8+
:renderers="renderers"
9+
validationMode="ValidateAndShow"
10+
:additionalErrors="getSchemaValidations"
11+
@change="onChange"
12+
)
13+
//- pre(v-html="JSON.stringify(data, null, 2)")
1214
</template>
1315

1416
<script setup lang="ts">
Lines changed: 84 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,103 @@
11
<template lang="pug">
2-
div password
3-
//- <!-- <control-wrapper v-bind="controlWrapper" :styles="styles" :isFocused="isFocused" :appliedOptions="appliedOptions">
4-
//- <v-text-field :type="passwordVisible ? 'text' : 'password'"
5-
//- :append-icon="passwordVisible ? 'mdi-eye' : 'mdi-eye-off'"
6-
//- @click:append="() => (passwordVisible = !passwordVisible)" :id="control.id + '-input'"
7-
//- :class="styles.control.input" :disabled="!control.enabled" :autofocus="appliedOptions.focus"
8-
//- :placeholder="appliedOptions.placeholder" :label="computedLabel" :hint="control.description"
9-
//- :persistent-hint="persistentHint()" :required="control.required" :error-messages="control.errors"
10-
//- :model-value="control.data" :maxlength="appliedOptions.restrict ? control.schema.maxLength : undefined
11-
//- " :size="appliedOptions.trim && control.schema.maxLength !== undefined
12-
//- ? control.schema.maxLength
13-
//- : undefined
14-
//- " v-bind="vuetifyProps('v-text-field')" @update:model-value="onChange" @focus="handleFocus" @blur="handleBlur" />
15-
//- </control-wrapper> -->
2+
//control-wrapper(v-bind="controlWrapper" :styles="styles" :isFocused="isFocused" :appliedOptions="appliedOptions")
3+
div.flex.q-col-gutter-sm
4+
q-input.col(
5+
:id="control.id + '-input'"
6+
:disable="!control.enabled"
7+
:placeholder="appliedOptions.placeholder"
8+
:label="computedLabel"
9+
type="password"
10+
:hint="control.description"
11+
:error="control.errors !== ''"
12+
:error-message="control.errors"
13+
:maxlength="appliedOptions.restrict ? control.schema.maxLength : undefined"
14+
:clearable="true"
15+
v-model="password"
16+
@update:model-value="onChangeControl"
17+
@focus="isFocused = true"
18+
@blur="isFocused = false"
19+
filled
20+
)
21+
//- :model-value="control.data"
22+
q-input.col(
23+
:id="control.id + '-input'"
24+
:disable="!control.enabled"
25+
label="Confirmation"
26+
type="password"
27+
:hint="control.description"
28+
:error="control.errors !== ''"
29+
:error-message="control.errors"
30+
v-model="confirm"
31+
:maxlength="appliedOptions.restrict ? control.schema.maxLength : undefined"
32+
:clearable="true"
33+
@update:model-value="onChangeControl"
34+
@focus="isFocused = true"
35+
@blur="isFocused = false"
36+
filled
37+
)
1638
</template>
1739

1840
<script lang="ts">
41+
import { defineComponent } from 'vue';
42+
import { rendererProps, useJsonFormsControl } from '@jsonforms/vue';
1943
import {
20-
// ControlElement,
21-
// JsonFormsRendererRegistryEntry,
22-
rankWith,
44+
isControl,
2345
isStringControl,
24-
and,
25-
formatIs,
46+
rankWith,
2647
} from '@jsonforms/core';
27-
import { defineComponent, ref } from 'vue';
28-
import {
29-
rendererProps,
30-
useJsonFormsControl,
31-
// RendererProps,
32-
} from '@jsonforms/vue';
33-
import { default as ControlWrapper } from './ControlWrapper.vue';
48+
import type { JsonFormsRendererRegistryEntry } from '@jsonforms/core';
49+
import { isArray, isObject, isString, iterate } from 'radash';
50+
import type { RendererProps } from '@jsonforms/vue';
51+
import type { ControlElement } from '@jsonforms/core';
52+
import { useQuasarControl } from '../util';
53+
import { ControlWrapper } from '@jsonforms/vue-vanilla';
3454
35-
const controlRenderer = defineComponent({
36-
name: 'password-control-renderer',
55+
const QPasswordControlRenderer = defineComponent({
56+
name: 'q-password-control-renderer',
3757
components: {
3858
ControlWrapper,
39-
// VTextField,
4059
},
4160
props: {
4261
...rendererProps<ControlElement>(),
4362
},
4463
setup(props: RendererProps<ControlElement>) {
45-
const passwordVisible = ref(false);
46-
47-
return {
48-
// ...useVuetifyControl(
49-
// useJsonFormsControl(props),
50-
// (value) => value || undefined,
51-
// 300
52-
// ),
53-
passwordVisible,
54-
};
64+
return useQuasarControl(
65+
useJsonFormsControl(props),
66+
(value) => isObject(value) ? value.value : value || undefined,
67+
)
68+
},
69+
data: () => ({
70+
password: ref(''),
71+
confirm: ref(''),
72+
}),
73+
watch: {
74+
'control.data': {
75+
deep: true,
76+
handler(val) {
77+
this.password = val
78+
},
79+
},
80+
},
81+
methods: {
82+
onChangeControl() {
83+
if (this.password === this.confirm) {
84+
this.onChange(this.password)
85+
}
86+
},
87+
isIterable(obj) {
88+
// checks for null and undefined
89+
if (obj == null) {
90+
return false;
91+
}
92+
return typeof obj[Symbol.iterator] === 'function';
93+
},
94+
},
95+
computed: {
96+
computedLabel() {
97+
return this.control.label === undefined ? this.control.schema.title : this.control.label;
98+
},
5599
},
56100
});
101+
export default QPasswordControlRenderer;
57102
58-
export default controlRenderer;
59-
60-
export const entry: JsonFormsRendererRegistryEntry = {
61-
renderer: controlRenderer,
62-
tester: rankWith(2, and(isStringControl, formatIs('password'))),
63-
};
64103
</script>

src/components/quasar-jsonform/controls/QStringControlRenderer.vue

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<template lang="pug">
22
//control-wrapper(v-bind="controlWrapper" :styles="styles" :isFocused="isFocused" :appliedOptions="appliedOptions")
33
div
4+
pre(v-html="JSON.stringify(control.data, null, 2)")
45
q-select(
56
v-if="suggestions !== undefined"
67
:model-value="control.data"
@@ -81,6 +82,10 @@ const QStringControlRenderer = defineComponent({
8182
return typeof obj[Symbol.iterator] === 'function';
8283
},
8384
},
85+
mounted() {
86+
console.log('this.control', this.control)
87+
console.log('this.control.dataa', this.control.data)
88+
},
8489
computed: {
8590
suggestions() {
8691
const suggestions = this.control.uischema.options?.suggestion;

src/components/quasar-jsonform/controls/index.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import QArrayControlRenderer from "./QArrayControlRenderer.vue";
33
import QDateControlRenderer from "./QDateControlRenderer.vue";
44
import QNumberControlRenderer from "./QNumberControlRenderer.vue";
55
import QPasswordControlRenderer from "./QPasswordControlRenderer.vue";
6-
import { isControl, isDateControl, isNumberControl, isPrimitiveArrayControl, rankWith, type JsonFormsRendererRegistryEntry } from "@jsonforms/core";
6+
import { and, formatIs, isControl, isDateControl, isNumberControl, isPrimitiveArrayControl, or, rankWith, scopeEndsWith, type JsonFormsRendererRegistryEntry } from "@jsonforms/core";
77

88
const QDateControlRendererEntry: JsonFormsRendererRegistryEntry = {
99
renderer: QDateControlRenderer,
@@ -27,12 +27,13 @@ export const QArrayControlRendererEntry: JsonFormsRendererRegistryEntry = {
2727

2828
export const QPasswordControlRendererEntry: JsonFormsRendererRegistryEntry = {
2929
renderer: QPasswordControlRenderer,
30-
tester: rankWith(2, isControl),
30+
tester: rankWith(2, or(and(isControl, formatIs('password')), scopeEndsWith('password'))),
3131
};
3232

3333
export const ControlsRenderer = [
3434
QDateControlRendererEntry,
3535
QNumberControlRendererEntry,
3636
QStringControlRendererEntry,
3737
QArrayControlRendererEntry,
38+
QPasswordControlRendererEntry,
3839
];

src/components/quasar-jsonform/util/composition.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ export const useQuasarControl = <
8282
: input.handleChange;
8383

8484
const onChange = (value: any) => {
85-
console.log('onChange', value);
85+
// console.log('onChange', value);
86+
// debugger
8687
changeEmitter(input.control.value.path, adaptValue(value));
8788
};
8889

@@ -116,9 +117,11 @@ export const useQuasarControl = <
116117
console.log('input', input.control.value.path, input.control.value.data)
117118
if (typeof input.control.value.data === 'undefined' || input.control.value.data === null && input.control.value.errors) {
118119
input.handleChange(input.control.value.path, input.control.value.schema.default || null)
119-
console.log('input.data', input.control.value.data)
120+
// console.log('input.data', input.control.value.data)
120121
}
121-
console.log('input.data', input.control.value)
122+
// console.log('input.data', input.control.value)
123+
// console.log('input.control.value.data', input.control.value.data)
124+
// input.handleChange(input.control.value.path, input.control.value.data)
122125

123126
return {
124127
...input,

src/components/quasar-jsonform/util/validator.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import Ajv from 'ajv';
44

55
export const createAjv = (options?: Options): Ajv => {
66
const ajv = createAjvCore(options);
7+
debugger
78
ajv.addFormat('password', (_) => true);
89
return ajv;
9-
};
10+
};

src/composables/useAgentsSchema.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ export default function useAgentsSchema() {
1111
"type": "string",
1212
"description": "Nom affiché"
1313
},
14+
// "password": {
15+
// "type": "string",
16+
// "description": "Mot de passe"
17+
// },
1418
"email": {
1519
"type": "string",
1620
"description": "Adresse e-mail"
@@ -61,6 +65,19 @@ export default function useAgentsSchema() {
6165
"required": true
6266
}
6367
},
68+
]
69+
},
70+
{
71+
"type": "HorizontalLayout",
72+
"elements": [
73+
// {
74+
// "type": "Control",
75+
// "label": "Password",
76+
// "scope": "#/properties/password",
77+
// "options": {
78+
// "format": "password"
79+
// }
80+
// },
6481
{
6582
"type": "Control",
6683
"label": "Email",

0 commit comments

Comments
 (0)