diff --git a/src/renderer/src/stories/JSONSchemaForm.js b/src/renderer/src/stories/JSONSchemaForm.js index c73e04526..c17ae04ac 100644 --- a/src/renderer/src/stories/JSONSchemaForm.js +++ b/src/renderer/src/stories/JSONSchemaForm.js @@ -40,10 +40,6 @@ const componentCSS = ` line-height: 1.4285em; } - .invalid { - background: rgb(255, 229, 228) !important; - } - .guided--form-label { display: block; width: 100%; @@ -320,11 +316,11 @@ export class JSONSchemaForm extends LitElement { validate = async (resolved) => { // Check if any required inputs are missing - const invalidInputs = await this.#validateRequirements(resolved); // get missing required paths - const isValid = this.requirementMode === "loose" ? true : !invalidInputs.length; + const requiredButNotSpecified = await this.#validateRequirements(resolved); // get missing required paths + const isValid = this.requirementMode === "loose" ? true : !requiredButNotSpecified.length; // Print out a detailed error message if any inputs are missing - let message = isValid ? "" : `${invalidInputs.length} required inputs are not specified properly.`; + let message = isValid ? "" : `${requiredButNotSpecified.length} required inputs are not specified properly.`; // Check if all inputs are valid const flaggedInputs = this.shadowRoot ? this.shadowRoot.querySelectorAll(".invalid") : []; @@ -376,11 +372,7 @@ export class JSONSchemaForm extends LitElement { #checkRequiredAfterChange = async (localPath) => { const path = [...localPath]; const name = path.pop(); - const element = this.shadowRoot - .querySelector(`#${localPath.join("-")}`) - .querySelector("jsonschema-input") - .getElement(); - const isValid = await this.triggerValidation(name, element, path, false); + const isValid = await this.triggerValidation(name, path, false); if (!isValid) return true; }; @@ -603,7 +595,7 @@ export class JSONSchemaForm extends LitElement { }; // Assume this is going to return as a Promise—even if the change function isn't returning one - triggerValidation = async (name, element, path = [], checkLinks = true) => { + triggerValidation = async (name, path = [], checkLinks = true) => { const parent = this.#get(path, this.resolved); const pathToValidate = [...(this.base ?? []), ...path]; @@ -644,12 +636,15 @@ export class JSONSchemaForm extends LitElement { } else { // For non-links, throw a basic requirement error if the property is required if (!errors.length && isRequired && !parent[name]) { - const schema = this.getSchema(localPath); - errors.push({ - message: `${schema.title ?? header(name)} is a required property.`, - type: "error", - missing: true, - }); // Throw at least a basic error if the property is required + // Skip simple required checks in loose mode + if (this.requirementMode !== "loose") { + const schema = this.getSchema(localPath); + errors.push({ + message: `${schema.title ?? header(name)} is a required property.`, + type: "error", + missing: true, + }); // Throw at least a basic error if the property is required + } } } @@ -676,8 +671,10 @@ export class JSONSchemaForm extends LitElement { warnings.forEach((info) => this.#addMessage(localPath, info, "warnings")); info.forEach((info) => this.#addMessage(localPath, info, "info")); + const input = this.getInput(localPath); + if (isValid && errors.length === 0) { - element.classList.remove("invalid"); + input.classList.remove("invalid"); const linkEl = this.#getLinkElement(externalPath); if (linkEl) linkEl.classList.remove("required", "conditional"); @@ -691,7 +688,7 @@ export class JSONSchemaForm extends LitElement { return true; } else { // Add new invalid classes and errors - element.classList.add("invalid"); + input.classList.add("invalid"); const linkEl = this.#getLinkElement(externalPath); if (linkEl) linkEl.classList.add("required", "conditional"); diff --git a/src/renderer/src/stories/JSONSchemaInput.js b/src/renderer/src/stories/JSONSchemaInput.js index 76a292498..a74c20532 100644 --- a/src/renderer/src/stories/JSONSchemaInput.js +++ b/src/renderer/src/stories/JSONSchemaInput.js @@ -30,6 +30,10 @@ export class JSONSchemaInput extends LitElement { display: block; } + :host(.invalid) .guided--input { + background: rgb(255, 229, 228) !important; + } + .guided--input { width: 100%; border-radius: 4px; @@ -106,12 +110,16 @@ export class JSONSchemaInput extends LitElement { // onValidate = () => {} updateData(value) { + if (this.value === value) return false; + const { path: fullPath } = this; const path = typeof fullPath === "string" ? fullPath.split("-") : [...fullPath]; const name = path.splice(-1)[0]; - const el = this.getElement(); - this.#triggerValidation(name, el, path); + + this.#triggerValidation(name, path); this.#updateData(fullPath, value); + + const el = this.getElement(); if (el.type === "checkbox") el.checked = value; else el.value = value; @@ -143,9 +151,9 @@ export class JSONSchemaInput extends LitElement { this.#activateTimeoutValidation(name, this.getElement(), path); }; - #triggerValidation = (name, el, path) => { + #triggerValidation = (name, path) => { this.#clearTimeoutValidation(); - return this.onValidate ? this.onValidate() : this.form ? this.form.triggerValidation(name, el, path) : ""; + return this.onValidate ? this.onValidate() : this.form ? this.form.triggerValidation(name, path) : ""; }; updated() { @@ -189,7 +197,7 @@ export class JSONSchemaInput extends LitElement { type: format, value: this.value, onSelect: (filePath) => this.#updateData(fullPath, filePath), - onChange: (filePath) => validateOnChange && this.#triggerValidation(name, el, path), + onChange: (filePath) => validateOnChange && this.#triggerValidation(name, path), onThrow: (...args) => this.#onThrow(...args), dialogOptions: this.form?.dialogOptions, dialogType: this.form?.dialogType, @@ -290,7 +298,7 @@ export class JSONSchemaInput extends LitElement { : [], onChange: async () => { this.#updateData(fullPath, list.items.length ? list.items.map((o) => o.value) : undefined); - if (validateOnChange) await this.#triggerValidation(name, list, path); + if (validateOnChange) await this.#triggerValidation(name, path); }, }); @@ -303,10 +311,7 @@ export class JSONSchemaInput extends LitElement { }); return html` -
validateOnChange && this.#triggerValidation(name, list, path)} - > +
validateOnChange && this.#triggerValidation(name, path)}> ${list} ${addButton}
`; @@ -317,11 +322,8 @@ export class JSONSchemaInput extends LitElement { return html`