From d9156d6949d65339ad7aa4ea58c6bb7add8e8d47 Mon Sep 17 00:00:00 2001 From: Adithya Jayasankar Date: Mon, 1 Jul 2024 08:52:01 +0530 Subject: [PATCH] throw required error only if property is visible --- package-lock.json | 12 +- .../schema-form/src/lib/model/formproperty.ts | 16 ++ .../json-schema-example.component.ts | 10 ++ .../required-only-if-visible.json | 157 ++++++++++++++++++ 4 files changed, 189 insertions(+), 6 deletions(-) create mode 100644 src/app/json-schema-example/required-only-if-visible.json diff --git a/package-lock.json b/package-lock.json index 237a1f01..2f038ad7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14248,19 +14248,19 @@ }, "projects/schema-form": { "name": "ngx-schema-form", - "version": "2.11.0", + "version": "2.12.0", "license": "MIT", "dependencies": { "tslib": "^2.3.1" }, "peerDependencies": { - "@angular/common": "^17.0.0", - "@angular/core": "^17.0.0", - "@angular/forms": "^17.0.0", - "@angular/platform-browser": "^17.0.0", + "@angular/common": "^18.0.0", + "@angular/core": "^18.0.0", + "@angular/forms": "^18.0.0", + "@angular/platform-browser": "^18.0.0", "jexl": "^2.2.2", "rxjs": "~7.4.0", - "typescript": "^5.2.2", + "typescript": "^5.4.5", "z-schema": "^4.2.2", "zone.js": "~0.14.2" } diff --git a/projects/schema-form/src/lib/model/formproperty.ts b/projects/schema-form/src/lib/model/formproperty.ts index e4e8ee43..5e911d7a 100644 --- a/projects/schema-form/src/lib/model/formproperty.ts +++ b/projects/schema-form/src/lib/model/formproperty.ts @@ -163,6 +163,22 @@ export abstract class FormProperty { */ public _runValidation(): any { let errors = this.schemaValidator(this._value) || []; + + // remove missing required property error if property is not visible + for (let i = errors.length - 1; i >= 0; i -= 1) { + const error = errors[i]; + if (error.code === "OBJECT_MISSING_REQUIRED_PROPERTY") { + let path = `${error.path.substring(1)}`; + if (path.substring(1) !== error.params[0]) { + path += `/${error.params.join("/")}`; + } + const requiredProperty = this.searchProperty(path); + if (requiredProperty && requiredProperty.visible === false) { + errors.splice(i, 1); + } + } + } + let customValidator = this.validatorRegistry.get(this.path); if (customValidator) { let customErrors = customValidator(this.value, this, this.findRoot()); diff --git a/src/app/json-schema-example/json-schema-example.component.ts b/src/app/json-schema-example/json-schema-example.component.ts index 551754b0..9a57fadd 100644 --- a/src/app/json-schema-example/json-schema-example.component.ts +++ b/src/app/json-schema-example/json-schema-example.component.ts @@ -17,6 +17,7 @@ import visibility_binding_example2 from './visibility-binding-example-schema2.js import visibility_binding_example3 from './visibility-binding-example-schema3.json'; import visibility_binding_example4 from './visibility-binding-example-schema4.json'; import sample_canonical_path from './sample-canonical-path.json'; +import required_only_if_visible from './required-only-if-visible.json'; import {AppService, AppData} from '../app.service'; import {ISchema} from 'ngx-schema-form'; @@ -46,6 +47,7 @@ export class JsonSchemaExampleComponent implements OnInit, OnDestroy { {label: 'Sample 6 - Visibility binding 3', event: this.changeSchemaVisibilityBinding3, selected: false}, {label: 'Sample 7 - Visibility binding 4', event: this.changeSchemaVisibilityBinding4, selected: false}, {label: 'Sample 8 - Canonical path', event: this.changeSchemaCanonicalPath, selected: false}, + {label: 'Sample 9 - Required only if visible', event: this.changeSchemaRequiredOnlyIfVisible, selected: false}, ]; constructor( @@ -247,6 +249,14 @@ export class JsonSchemaExampleComponent implements OnInit, OnDestroy { this.actions = {}; } + changeSchemaRequiredOnlyIfVisible() { + this.schema = required_only_if_visible as unknown as ISchema; + this.model = {}; + this.fieldBindings = {}; + this.fieldValidators = {}; + this.actions = {}; + } + disableAll() { Object.keys(this.schema.properties).map(prop => { this.schema.properties[prop].readOnly = true; diff --git a/src/app/json-schema-example/required-only-if-visible.json b/src/app/json-schema-example/required-only-if-visible.json new file mode 100644 index 00000000..02b9b9fa --- /dev/null +++ b/src/app/json-schema-example/required-only-if-visible.json @@ -0,0 +1,157 @@ +{ + "properties": { + "checkbox": { + "type": "boolean", + "title": "Checkbox", + "widget": "checkbox" + }, + "select": { + "type": "string", + "title": "Select", + "widget": "select", + "oneOf": [ + { + "description": "Option #1", + "enum": ["Option #1"] + }, + { + "description": "Option #2", + "enum": ["Option #2"] + }, + { + "description": "Option #3", + "enum": ["Option #3"] + } + ], + "visibleIf": { + "checkbox": [true] + } + }, + "multi-select": { + "type": "array", + "title": "Multi Select", + "widget": "select", + "minItems": 2, + "items": { + "type": "string", + "oneOf": [ + { + "description": "Option #1", + "enum": ["Option #1"] + }, + { + "description": "Option #2", + "enum": ["Option #2"] + }, + { + "description": "Option #3", + "enum": ["Option #3"] + } + ] + }, + "visibleIf": { + "checkbox": [true] + } + }, + "string": { + "type": "string", + "title": "String - Visible if Checkbox is checked", + "visibleIf": { + "checkbox": [true] + } + }, + "number": { + "type": "number", + "title": "Number - Visible if String is 'a'", + "widget": "number", + "visibleIf": { + "string": ["a"] + } + }, + "array": { + "type": "array", + "title": "Array", + "minItems": 2, + "items": { + "type": "object", + "properties": { + "array-checkbox": { + "type": "boolean", + "title": "Checkbox", + "widget": "checkbox" + }, + "array-select": { + "type": "string", + "title": "Select", + "widget": "select", + "oneOf": [ + { + "description": "Option #1", + "enum": ["Option #1"] + }, + { + "description": "Option #2", + "enum": ["Option #2"] + }, + { + "description": "Option #3", + "enum": ["Option #3"] + } + ], + "visibleIf": { + "array-checkbox": [true] + } + }, + "array-multi-select": { + "type": "array", + "title": "Multi Select", + "widget": "select", + "minItems": 2, + "items": { + "type": "string", + "oneOf": [ + { + "description": "Option #1", + "enum": ["Option #1"] + }, + { + "description": "Option #2", + "enum": ["Option #2"] + }, + { + "description": "Option #3", + "enum": ["Option #3"] + } + ] + }, + "visibleIf": { + "array-checkbox": [true] + } + }, + "array-string": { + "type": "string", + "title": "String - Visible if Checkbox is checked", + "visibleIf": { + "array-checkbox": [true] + } + }, + "array-number": { + "type": "number", + "title": "Number - Visible if String is 'a'", + "widget": "number", + "visibleIf": { + "array-string": ["a"] + } + } + }, + "required": [ + "array-select", + "array-multi-select", + "array-string", + "array-number" + ] + } + } + }, + "required": ["select", "multi-select", "string", "number", "array"] +}