Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes Ajv 8 breaking changes, adds additional editor enhancements #1038

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions projects/swimlane/ngx-ui/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## HEAD (unreleased)

- Enhancement(`ngx-calendar`): Supports selecting a range of dates with hours and minutes
- Enhancement(`ngx-json-editor`): Fixes Ajv breaking changes unaccounted for in 47.1.0. Adds enhancements to allow for overriding the default Ajv options, and adding extra formats and keywords

## 48.0.0 (2023-06-17)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
} from './json-editor-node-flat/node-types/property-config/property-config.component';

import type { QueryList } from '@angular/core';
import { Format, InstanceOptions, KeywordDefinition } from 'ajv';

@Component({
selector: 'ngx-json-editor-flat',
Expand Down Expand Up @@ -51,6 +52,12 @@ export class JsonEditorFlatComponent extends JsonEditor implements OnInit, OnCha

@Input() inputControlTemplate: TemplateRef<unknown>;

@Input() ajvOptions: InstanceOptions;

@Input() additionalKeywords?: Array<string | KeywordDefinition>;

@Input() additionalFormats?: Map<string, Format>;

@ContentChildren(JsonEditorNodeFlatComponent) nodeElms: QueryList<JsonEditorNodeFlatComponent>;

@ViewChild('propertyConfigTmpl') propertyConfigTmpl: TemplateRef<PropertyConfigComponent>;
Expand All @@ -71,6 +78,15 @@ export class JsonEditorFlatComponent extends JsonEditor implements OnInit, OnCha
if (this.formats.length && this.schemaBuilderMode) {
this.buildCustomFormats();
}
if (!this.schemaValidator && this.ajvOptions) {
this.schemaValidatorService.setAjvOptions(this.ajvOptions);
}
if (this.additionalKeywords) {
this.schemaValidatorService.addAjvKeywords(this.additionalKeywords);
}
if (this.additionalFormats) {
this.schemaValidatorService.addAjvFormats(this.additionalFormats);
}
}

ngOnChanges(changes: SimpleChanges) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,11 +159,11 @@ export class JsonEditorNode implements OnInit, OnChanges {

if (this.errors && this.errors.length) {
this.ownErrors = this.errors.filter(e => {
return e.dataPath === this.path;
return e.instancePath === this.path;
});

this.childrenErrors = this.errors.filter(e => {
return e.dataPath.startsWith(this.path);
return e.instancePath.startsWith(this.path);
});
}
this.childrenValid = this.childrenErrors.length === 0;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
import { Input, Output, EventEmitter, OnChanges, SimpleChanges, ChangeDetectorRef, Directive } from '@angular/core';
import {
Input,
Output,
EventEmitter,
OnChanges,
SimpleChanges,
ChangeDetectorRef,
Directive,
OnInit
} from '@angular/core';
import { SchemaValidatorService } from './schema-validator.service';
import { JSONEditorSchema } from './json-editor.helper';
import { debounceable } from '../../decorators/debounceable/debounceable.decorator';
import { Format, InstanceOptions, KeywordDefinition } from 'ajv';

@Directive()
export class JsonEditor implements OnChanges {
export class JsonEditor implements OnInit, OnChanges {
@Input() model: any;

@Input() schema: JSONEditorSchema;
Expand All @@ -17,6 +27,12 @@ export class JsonEditor implements OnChanges {

@Input() showKnownProperties = false;

@Input() ajvOptions?: InstanceOptions;

@Input() additionalKeywords?: Array<string | KeywordDefinition>;

@Input() additionalFormats?: Map<string, Format>;

@Output() modelChange: EventEmitter<any> = new EventEmitter();

@Output() schemaUpdate: EventEmitter<JSONEditorSchema> = new EventEmitter();
Expand All @@ -25,6 +41,21 @@ export class JsonEditor implements OnChanges {

constructor(protected schemaValidatorService: SchemaValidatorService, protected cdr: ChangeDetectorRef) {}

/**
* On component initialization, set Ajv options if provided
*/
ngOnInit() {
if (!this.schemaValidator && this.ajvOptions) {
this.schemaValidatorService.setAjvOptions(this.ajvOptions);
}
if (this.additionalKeywords) {
this.schemaValidatorService.addAjvKeywords(this.additionalKeywords);
}
if (this.additionalFormats) {
this.schemaValidatorService.addAjvFormats(this.additionalFormats);
}
}

ngOnChanges(changes: SimpleChanges) {
if (changes.schema) {
this.schema = JSON.parse(JSON.stringify(this.schema));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ export class ObjectNode implements OnInit, OnChanges {
return `['${propName}']`;
}

return `.${propName}`;
return `/${propName}`;
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,56 @@
import Ajv from 'ajv';
import Ajv, { Format, InstanceOptions, KeywordDefinition } from 'ajv';
import addFormats from 'ajv-formats';
import { Injectable } from '@angular/core';

@Injectable({
providedIn: 'root'
})
export class SchemaValidatorService {
ajv = new Ajv({
allErrors: true
allErrors: true,
strict: true
});

constructor() {
addFormats(this.ajv);
this.ajv.addKeyword('$meta');
this.ajv.addFormat('password', '.*');
this.ajv.addFormat('code', '.*');
this.ajv.addFormat('binary', '.*');
}

/**
* Allows for overriding the default set Ajv Options
* @param opts {InstanceOptions} The Ajv options to override
*/
setAjvOptions(opts: InstanceOptions): void {
this.ajv.opts = opts;
}

/**
* Allows for adding Ajv keywords
* @param keywords {Array<string | KeywordDefinition>} The Ajv keywords to add
*/
addAjvKeywords(keywords: Array<string | KeywordDefinition>): void {
if (Array.isArray(keywords)) {
keywords.forEach((keyword: string | KeywordDefinition) => {
this.ajv.addKeyword(keyword);
});
}
}

/**
* Allows for adding Ajv formats
* @param formats {Map<string, Format>} The Ajv formats to add
*/
addAjvFormats(formats: Map<string, Format>): void {
if (formats) {
formats.forEach((formatValue: Format, formatName: string) => {
this.ajv.addFormat(formatName, formatValue);
});
}
}

/**
* Validates schemas of a specified type
*/
Expand Down