Skip to content

Commit 2aece91

Browse files
authored
Merge pull request #28 from webgme/required-prop-fix
Required prop fix
2 parents dc18b27 + e415d99 commit 2aece91

File tree

3 files changed

+48
-27
lines changed

3 files changed

+48
-27
lines changed

src/lib/controls/AnyOfControl.svelte

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@
2626
$: resetSelected(schemas);
2727
$: resetData(selected, type);
2828
29+
function isObjSchema() {
30+
return isObjectSchema({ type: selected?.type ?? type });
31+
}
32+
2933
function getKey(schema: JSONSchema7) {
3034
return keys.get(schema) ?? "";
3135
}
@@ -50,24 +54,29 @@
5054
}
5155
5256
async function resetData(selected: JSONSchema7 | null, type: JSONSchema7['type']) {
53-
if (isObjectSchema({ type: selected?.type ?? type })) {
54-
if (selectedProps) {
55-
const omitted = omit(data, selectedProps);
56-
// make sure it's changed (to prevent infinite loop)
57-
if (Object.keys(data).length != Object.keys(omitted).length) {
58-
await tick();
59-
data = omitted;
60-
}
57+
let newData = data;
58+
if (isObjSchema() && (selected != null)) {
59+
if (selectedProps && data) {
60+
newData = omit(data, selectedProps, { keepUnchanged: true });
6161
}
6262
else if ((data == null) || !isEmpty(data)) {
63-
await tick();
64-
data = {};
63+
newData = {};
6564
}
66-
selectedProps = Object.keys(selected?.properties ?? {})
6765
}
6866
else {
69-
if (data != null) data = undefined;
70-
if (selectedProps != null) selectedProps = undefined;
67+
newData = undefined;
68+
}
69+
if (newData !== data) {
70+
await tick();
71+
data = newData;
72+
}
73+
resetSelectedProps();
74+
}
75+
76+
function resetSelectedProps() {
77+
const newSelectedProps = isObjSchema() ? Object.keys(selected?.properties ?? {}) : undefined;
78+
if (newSelectedProps !== selectedProps) {
79+
selectedProps = newSelectedProps;
7180
}
7281
}
7382
</script>

src/lib/controls/ObjectControl.svelte

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<script lang="ts">
22
import type { JSONSchema7Definition } from "json-schema";
3-
import { hasRequired as checkRequired, isBoolean } from "$lib/utilities";
3+
import { isBoolean } from "$lib/utilities";
44
import UISchema from "$lib/UISchema";
55
import Accordion, { Panel, Header, Content } from '@smui-extra/accordion';
66
import IconButton, { Icon } from '@smui/icon-button';
@@ -21,9 +21,8 @@
2121
2222
$: uiOptions = UISchema.Options.get(uischema);
2323
$: hasProps = !!Object.keys(properties ?? {}).length || !!Object.keys(anyOf ?? {}).length;
24-
$: hasRequired = isRequired || checkRequired({ properties, required, anyOf });
2524
$: ignoreEmpty = $uiOptions.ignoreEmpty ?? false;
26-
$: updateEnabled(data, hasRequired, ignoreEmpty);
25+
$: updateEnabled(data, isRequired, ignoreEmpty);
2726
$: updateData(enabled);
2827
$: updateOpen(enabled);
2928
$: updateOpen($uiOptions.collapse);
@@ -34,8 +33,8 @@
3433
open = hasProps && (isBoolean(arg) ? arg : !UISchema.shouldCollapse($$props, arg, open));
3534
}
3635
37-
function updateEnabled(data: any, hasRequired: boolean, ignoreEmpty: boolean) {
38-
const shouldEnable = hasRequired || ignoreEmpty || !!data;
36+
function updateEnabled(data: any, isRequired: boolean | undefined, ignoreEmpty: boolean) {
37+
const shouldEnable = isRequired || ignoreEmpty || !!data;
3938
if (shouldEnable != enabled) {
4039
enabled = shouldEnable;
4140
}
@@ -59,11 +58,11 @@
5958
bind:open
6059
variant="unelevated"
6160
disabled={!enabled}
62-
class={(hasRequired || ignoreEmpty) ? "no-disable" : undefined}
61+
class={(isRequired || ignoreEmpty) ? "no-disable" : undefined}
6362
nonInteractive={!hasProps}
6463
>
6564
<Header>
66-
{#if !hasRequired && !ignoreEmpty}
65+
{#if !isRequired && !ignoreEmpty}
6766
<IconButton type="button" toggle bind:pressed={enabled} size="button" on:click={stop}>
6867
<Icon class="material-icons" on>check_box</Icon>
6968
<Icon class="material-icons">check_box_outline_blank</Icon>

src/lib/utilities.ts

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,26 @@ export function isObject(arg: any): arg is object {
4747
return Object.prototype.toString.call(arg) === '[object Object]';
4848
}
4949

50-
export function omit<T extends Record<any, any>, K extends keyof T>(obj: T, keys: K[]) {
51-
return Object.keys(obj)
52-
.filter(key => !keys.includes(key as K))
53-
.reduce((acc, key) => {
54-
acc[key as keyof typeof acc] = obj[key];
55-
return acc;
56-
}, {} as Omit<T, K>)
50+
/**
51+
* Omits properties from the given object.
52+
*
53+
* @param obj The object to omit properties from
54+
* @param keys The array of property keys to omit from the object
55+
* @param [options] Options for the omit function:
56+
* {
57+
* keepUnchanged: True to return the original object if no properties were omitted. Defaults to false.
58+
* }
59+
* @return An object with the given properties omitted
60+
*/
61+
export function omit<T extends Record<any, any>, K extends keyof T>(obj: T, keys: K[], options?: { keepUnchanged: boolean }) {
62+
const { keepUnchanged = false } = options ?? {};
63+
const objKeys = Object.keys(obj);
64+
const keepKeys = objKeys.filter(key => !keys.includes(key as K));
65+
const keepObj = (keepKeys.length === objKeys.length) && keepUnchanged;
66+
return keepObj ? obj : keepKeys.reduce((acc, key) => {
67+
acc[key as keyof typeof acc] = obj[key];
68+
return acc;
69+
}, {} as Omit<T, K>)
5770
}
5871

5972
export function isDefined<T>(value: T | undefined): value is T {

0 commit comments

Comments
 (0)