Skip to content

Commit 4cb46f7

Browse files
authored
Merge pull request #36 from webgme/issue/any-of-set-selected
`AnyOf` Selection
2 parents c6b2010 + 720ddfd commit 4cb46f7

File tree

5 files changed

+51
-49
lines changed

5 files changed

+51
-49
lines changed

src/lib/SchemaForm.svelte

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,12 @@
44
import DownloadOptions, { type DataTransform } from './DownloadOptions';
55
import UISchema from "./UISchema";
66
import JsonSchemaDereferencer from "@json-schema-tools/dereferencer";
7-
import Ajv, { type ValidateFunction } from "ajv";
8-
import ajvFormats from "ajv-formats";
7+
import Validator, { ValidationError, type ValidateFunction } from "./Validator";
98
import mergeAllOf from "json-schema-merge-allof";
109
import Paper, { Title, Subtitle, Content } from '@smui/paper';
1110
import createMountedEventDispatcher from './createMountedEventDispatcher';
1211
import ObjectProps from "./controls/ObjectProps.svelte";
1312
import Control from "./Control.svelte";
14-
import ValidationError from "./ValidationError";
1513
import { isObjectSchema, isString, isBoolean } from './utilities';
1614
import libVersion from "./version";
1715
@@ -26,8 +24,6 @@
2624
* properly (so `.default` is `undefined`).
2725
*/
2826
const Dereferencer: typeof JsonSchemaDereferencer = (<any>JsonSchemaDereferencer).default ?? JsonSchemaDereferencer;
29-
const ajv = new Ajv();
30-
ajvFormats(ajv);
3127
const actions = {
3228
get blob() {
3329
return getBlob();
@@ -52,7 +48,7 @@
5248
});
5349
5450
$: try {
55-
validator = ajv.compile(schema);
51+
validator = Validator.compile(schema);
5652
}
5753
catch (error) {
5854
dispatch("error", error);

src/lib/ValidationError.ts

Lines changed: 0 additions & 12 deletions
This file was deleted.

src/lib/Validator.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import Ajv, { type ErrorObject, type ValidateFunction } from "ajv";
2+
import ajvFormats from "ajv-formats";
3+
4+
const ajv = new Ajv()
5+
ajvFormats(ajv)
6+
7+
export default ajv
8+
9+
export class ValidationError extends Error {
10+
errors: ErrorObject[]
11+
12+
constructor(errors: ErrorObject[] | false) {
13+
super("Data is invalid for JSON schema");
14+
this.errors = errors || []
15+
}
16+
}
17+
18+
export type { ErrorObject, ValidateFunction }

src/lib/controls/AnyOfControl.svelte

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<script lang="ts">
22
import type { JSONSchema7, JSONSchema7Definition } from "json-schema";
3+
import Validator from "$lib/Validator";
34
import UISchema from "$lib/UISchema";
45
import deepEquals from "fast-deep-equal";
56
import { isObjectSchema, omit, getLabel, isEmpty } from "$lib/utilities";
@@ -20,15 +21,13 @@
2021
const keys = new WeakMap<JSONSchema7, string>();
2122
let schemas: JSONSchema7[] = [];
2223
let selected: JSONSchema7 | null = null;
23-
let selectedProps: string[] | undefined;
2424
2525
$: uiOptions = UISchema.Options.get(uischema);
2626
$: updateSchemas(anyOf);
2727
$: resetSelected(schemas);
28-
$: resetData(selected, type);
2928
30-
function isObjSchema() {
31-
return isObjectSchema({ type: selected?.type ?? type });
29+
function isObjSchema(schema: JSONSchema7 | null = selected) {
30+
return isObjectSchema({ type: schema?.type ?? type });
3231
}
3332
3433
function getKey(schema: JSONSchema7) {
@@ -48,38 +47,38 @@
4847
}
4948
}
5049
51-
function resetSelected(schemas: JSONSchema7[]) {
52-
if ((selected == null) ? force : !schemas.includes(selected)) {
53-
selected = force ? schemas[0] : null;
54-
}
55-
}
56-
57-
async function resetData(selected: JSONSchema7 | null, type: JSONSchema7['type']) {
58-
await tick();
59-
let newData = data;
60-
if (isObjSchema() && (selected != null)) {
61-
if (selectedProps && data) {
62-
newData = omit(data, selectedProps, { keepUnchanged: true });
50+
async function setSelected(value: JSONSchema7 | null) {
51+
if (selected !== value) {
52+
let newData = data;
53+
if (isObjSchema(value) && (value != null)) {
54+
if ((selected != null) && isObjSchema() && !isEmpty(data ?? {})) {
55+
const selectedProps = Object.keys(selected?.properties ?? {});
56+
newData = omit(data, selectedProps, { keepUnchanged: true });
57+
}
58+
else if ((data == null) || !isEmpty(data)) {
59+
newData = {};
60+
}
6361
}
64-
else if ((data == null) || !isEmpty(data)) {
65-
newData = {};
62+
else {
63+
newData = undefined;
6664
}
65+
if (newData != data) {
66+
data = newData;
67+
}
68+
selected = value;
6769
}
68-
else {
69-
newData = undefined;
70-
}
71-
if (newData !== data) {
72-
data = newData;
73-
}
74-
resetSelectedProps();
7570
}
7671
77-
function resetSelectedProps() {
78-
const newSelectedProps = isObjSchema() ? Object.keys(selected?.properties ?? {}) : undefined;
79-
if (!deepEquals(newSelectedProps?.sort(), selectedProps?.sort())) {
80-
selectedProps = newSelectedProps;
72+
function resetSelected(schemas: JSONSchema7[]) {
73+
let newSelected = schemas.find(schema => Validator.validate(schema, data)) ?? null;
74+
if (force && (newSelected == null)) {
75+
newSelected = schemas[0];
76+
}
77+
if (newSelected !== selected) {
78+
selected = newSelected;
8179
}
8280
}
81+
8382
</script>
8483

8584
<Paper variant="unelevated" class="jsonschema-form-control control-anyof">
@@ -93,7 +92,8 @@
9392
disabled={$uiOptions.readonly}
9493
menu$class="control-anyof-menu"
9594
menu$portal
96-
bind:value={selected}
95+
value={selected}
96+
on:SMUISelect:change={(event) => setSelected(event.detail.value)}
9797
>
9898
{#if !force}
9999
<Option value={null} />

src/lib/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Reexport your entry components here
22
export { default as default } from "./SchemaForm.svelte";
33
export type { JSONSchema7 } from "json-schema";
4-
export { default as ValidationError } from "./ValidationError";
4+
export { ValidationError } from "./Validator";
55
export type { default as UISchema } from "./UISchema";
66
export type { default as DownloadOptions } from "./DownloadOptions";

0 commit comments

Comments
 (0)