Skip to content

Commit

Permalink
Merge pull request #1 in LFOR/lhncbc-ngx-schema-form from customize-f…
Browse files Browse the repository at this point in the history
…or-fhir to master

* commit 'abd9d879aa6433ea166afae09db441155fd85495':
  Add unit tests for changes and address review comments
  Fix typo in "modifierExtension"
  Add a comment
  Address review comments
  Update change log and urls in package.json
  Customize create properties for FHIR Extension
  Bump url-parse from 1.5.1 to 1.5.3
  Bump tar from 6.1.4 to 6.1.11
  • Loading branch information
akanduru committed Aug 31, 2022
2 parents 12eaa24 + abd9d87 commit 5e66085
Show file tree
Hide file tree
Showing 8 changed files with 141 additions and 44 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# 2.6.6-forked (2022-08-26)

- Customize creating of form property for FHIR Extension schema.

# 2.6.6 (2021-08-12)

- Fix HTML IDs in elements nested in arrays
Expand Down
12 changes: 6 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 6 additions & 5 deletions projects/schema-form/package.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"name": "ngx-schema-form",
"version": "2.6.6",
"name": "@lhncbc/ngx-schema-form",
"version": "2.6.6-forked",
"repository": {
"type": "git",
"url": "git+https://github.com/guillotinaweb/ngx-schema-form"
"url": "git+https://github.com/lhncbc/ngx-schema-form"
},
"keywords": [
"angular",
Expand All @@ -13,15 +13,16 @@
],
"license": "MIT",
"bugs": {
"url": "https://github.com/guillotinaweb/ngx-schema-form/issues"
"url": "https://github.com/lhncbc/ngx-schema-form/issues"
},
"contributors": [
"Frank Bessou <[email protected]>",
"Eric Brehault <[email protected]>",
"Simon Bats <[email protected]>",
"Gabor Pankotay <[email protected]>",
"Juan Manuel Verges",
"Daniele Pecora <[email protected]>"
"Daniele Pecora <[email protected]>",
"Ajay Kanduru <[email protected]>"
],
"dependencies": {
"tslib": "^2.0.0"
Expand Down
6 changes: 6 additions & 0 deletions projects/schema-form/src/lib/form.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,16 +69,21 @@ export class FormComponent implements OnChanges, ControlValueAccessor {

@Input() bindings: { [path: string]: Binding } = {};

// tslint:disable-next-line:no-output-on-prefix
@Output() onChange = new EventEmitter<{ value: any }>();

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

@Output() isValid = new EventEmitter<boolean>();

// tslint:disable-next-line:no-output-on-prefix
@Output() onErrorChange = new EventEmitter<{ value: any[] }>();

// tslint:disable-next-line:no-output-on-prefix
@Output() onErrorsChange = new EventEmitter<{value: any}>();

@Output() modelReset = new EventEmitter<{value: any}>();

rootProperty: FormProperty = null;

private onChangeCallback: any;
Expand Down Expand Up @@ -156,6 +161,7 @@ export class FormComponent implements OnChanges, ControlValueAccessor {
if (this.schema && (changes.model || changes.schema )) {
this.rootProperty.reset(this.model, false);
this.cdr.detectChanges();
this.modelReset.next({value: this.rootProperty.value});
}

}
Expand Down
27 changes: 13 additions & 14 deletions projects/schema-form/src/lib/model/arrayproperty.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,26 +21,25 @@ export class ArrayProperty extends PropertyGroup {
}

addItem(value: any = null): FormProperty {
let newProperty = this.addProperty();
newProperty.reset(value, false);
return newProperty;
return this.addProperty(value);
}

private addProperty() {
let itemSchema = this.schema.items
if (Array.isArray(this.schema.items)) {
const itemSchemas = this.schema.items as object[]
private addProperty(value) {
let itemSchema = this.schema.items;
if (Array.isArray(itemSchema)) {
const itemSchemas = itemSchema as object[];
if (itemSchemas.length > (<FormProperty[]>this.properties).length) {
itemSchema = itemSchema[(<FormProperty[]>this.properties).length]
itemSchema = itemSchema[(<FormProperty[]>this.properties).length];
} else if (this.schema.additionalItems) {
itemSchema = this.schema.additionalItems
itemSchema = this.schema.additionalItems;
} else {
// souldn't add new items since schema is undefined for the item at its position
return null
// shouldn't add new items since schema is undefined for the item at its position
return null;
}
}
let newProperty = this.formPropertyFactory.createProperty(itemSchema, this);
const newProperty = this.formPropertyFactory.createProperty(itemSchema, this, null, value);
(<FormProperty[]>this.properties).push(newProperty);
newProperty.reset(value, false);
return newProperty;
}

Expand Down Expand Up @@ -86,9 +85,9 @@ export class ArrayProperty extends PropertyGroup {


private resetProperties(value: any) {
for (let idx in value) {
for (const idx in value) {
if (value.hasOwnProperty(idx)) {
let property = this.addProperty();
const property = this.addProperty(value[idx]);
property.reset(value[idx], true);
}
}
Expand Down
9 changes: 5 additions & 4 deletions projects/schema-form/src/lib/model/formpropertyfactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export class FormPropertyFactory {
private logger: LogService) {
}

createProperty(schema: ISchema, parent: PropertyGroup = null, propertyId?: string): FormProperty {
createProperty(schema: ISchema, parent: PropertyGroup = null, propertyId: string = null, value?: any): FormProperty {
let newProperty = null;
let path = '';
let _canonicalPath = '';
Expand All @@ -33,7 +33,7 @@ export class FormPropertyFactory {
path += '*';
_canonicalPath += '*';
} else {
throw 'Instanciation of a FormProperty with an unknown parent type: ' + parent.type;
throw new Error('Instanciation of a FormProperty with an unknown parent type: ' + parent.type);
}
_canonicalPath = (parent._canonicalPath || parent.path) + _canonicalPath;
} else {
Expand All @@ -43,7 +43,7 @@ export class FormPropertyFactory {

if (schema.$ref) {
const refSchema = this.schemaValidatorFactory.getSchema(parent.root.schema, schema.$ref);
newProperty = this.createProperty(refSchema, parent, path);
newProperty = this.createProperty(refSchema, parent, path, value);
} else {
const type: FieldType = this.isUnionType(schema.type)
&& this.isValidNullableUnionType(schema.type as TNullableFieldType)
Expand All @@ -54,7 +54,8 @@ export class FormPropertyFactory {
if (PROPERTY_TYPE_MAPPING[type]) {
if (type === 'object' || type === 'array') {
newProperty = PROPERTY_TYPE_MAPPING[type](
this.schemaValidatorFactory, this.validatorRegistry, this.expressionCompilerFactory, schema, parent, path, this, this.logger);
this.schemaValidatorFactory, this.validatorRegistry, this.expressionCompilerFactory, schema, parent, path, this, this.logger,
value);
} else {
newProperty = PROPERTY_TYPE_MAPPING[type](
this.schemaValidatorFactory, this.validatorRegistry, this.expressionCompilerFactory, schema, parent, path, this.logger);
Expand Down
71 changes: 61 additions & 10 deletions projects/schema-form/src/lib/model/objectproperty.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,14 @@ import { DefaultLogService, LogLevel } from '../log.service';

describe('ObjectProperty', () => {

let A_VALIDATOR_REGISTRY = new ValidatorRegistry();
let A_SCHEMA_VALIDATOR_FACTORY = new ZSchemaValidatorFactory();
let A_PROPERTY_BINDING_REGISTRY=new PropertyBindingRegistry();
let A_EXPRESSION_COMPILER_FACTORY = new JEXLExpressionCompilerFactory();
let A_LOGGER = new DefaultLogService(LogLevel.off);
let A_FORM_PROPERTY_FACTORY = new FormPropertyFactory(A_SCHEMA_VALIDATOR_FACTORY, A_VALIDATOR_REGISTRY, A_PROPERTY_BINDING_REGISTRY, A_EXPRESSION_COMPILER_FACTORY, A_LOGGER);

const A_VALIDATOR_REGISTRY = new ValidatorRegistry();
const A_SCHEMA_VALIDATOR_FACTORY = new ZSchemaValidatorFactory();
const A_PROPERTY_BINDING_REGISTRY = new PropertyBindingRegistry();
const A_EXPRESSION_COMPILER_FACTORY = new JEXLExpressionCompilerFactory();
const A_LOGGER = new DefaultLogService(LogLevel.off);
const A_FORM_PROPERTY_FACTORY = new FormPropertyFactory(A_SCHEMA_VALIDATOR_FACTORY, A_VALIDATOR_REGISTRY, A_PROPERTY_BINDING_REGISTRY,
A_EXPRESSION_COMPILER_FACTORY, A_LOGGER);


const THE_OBJECT_SCHEMA: ISchema = {
type: 'object',
Expand All @@ -31,6 +32,7 @@ describe('ObjectProperty', () => {
};

let objProperty: ObjectProperty;
let value: any = null;


beforeEach(() => {
Expand All @@ -42,18 +44,67 @@ describe('ObjectProperty', () => {
THE_OBJECT_SCHEMA,
null,
'',
A_LOGGER
A_LOGGER,
value
);
});

it('should create same properties as in the schema', () => {

for (let propertyId in THE_OBJECT_SCHEMA.properties) {
for (const propertyId in THE_OBJECT_SCHEMA.properties) {
if (THE_OBJECT_SCHEMA.properties.hasOwnProperty(propertyId)) {
const property = objProperty.getProperty(propertyId);
expect(property).toBeDefined();
}
}
});

it('should create same properties as in schema with arbitrary parent path', () => {
value = {FOO: 1};
objProperty = new ObjectProperty(
A_FORM_PROPERTY_FACTORY,
A_SCHEMA_VALIDATOR_FACTORY,
A_VALIDATOR_REGISTRY,
A_EXPRESSION_COMPILER_FACTORY,
THE_OBJECT_SCHEMA,
null,
'/abc/def/*',
A_LOGGER,
value
);
for (const propertyId in THE_OBJECT_SCHEMA.properties) {
if (THE_OBJECT_SCHEMA.properties.hasOwnProperty(propertyId)) {
let property = objProperty.getProperty(propertyId);
const property = objProperty.getProperty(propertyId);
expect(property).toBeDefined();
}
}
});

['extension', 'modifierExtension'].forEach((field) => {
it('Special handling for ' + field + ': should create same properties as in value', () => {
value = {FOO: 1};
objProperty = new ObjectProperty(
A_FORM_PROPERTY_FACTORY,
A_SCHEMA_VALIDATOR_FACTORY,
A_VALIDATOR_REGISTRY,
A_EXPRESSION_COMPILER_FACTORY,
THE_OBJECT_SCHEMA,
null,
'/abc/' + field + '/*',
A_LOGGER,
value
);
for (const propertyId in THE_OBJECT_SCHEMA.properties) {
if (THE_OBJECT_SCHEMA.properties.hasOwnProperty(propertyId)) {
const property = objProperty.getProperty(propertyId);
if (value.hasOwnProperty(propertyId)) {
expect(property).toBeDefined();
} else {
expect(property).toBeUndefined();
}
}
}
});
});

});
45 changes: 40 additions & 5 deletions projects/schema-form/src/lib/model/objectproperty.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,25 @@ export class ObjectProperty extends PropertyGroup {
schema: ISchema,
parent: PropertyGroup,
path: string,
logger: LogService) {
logger: LogService,
value?: any) {
super(schemaValidatorFactory, validatorRegistry, expressionCompilerFactory, schema, parent, path, logger);
this.createProperties();
if (path.match(/\/(extension|modifierExtension)\/\*$/)) {
// Special handling for extension schema.
this.createPropertiesExtension(value);
} else {
this.createProperties();
}
}

setValue(value: any, onlySelf: boolean) {
for (const propertyId in value) {
if (value.hasOwnProperty(propertyId)) {
if (!this.properties[propertyId]) {
const propertySchema = this.schema.properties[propertyId];
this.properties[propertyId] = this.formPropertyFactory.createProperty(propertySchema, this, propertyId, value[propertyId]);
this.propertiesId.push(propertyId);
}
this.properties[propertyId].setValue(value[propertyId], true);
}
}
Expand All @@ -40,7 +51,7 @@ export class ObjectProperty extends PropertyGroup {

resetProperties(value: any) {
for (const propertyId in this.schema.properties) {
if (this.schema.properties.hasOwnProperty(propertyId)) {
if (this.properties[propertyId] && this.schema.properties.hasOwnProperty(propertyId)) {
this.properties[propertyId].reset(value[propertyId], true);
}
}
Expand All @@ -58,6 +69,29 @@ export class ObjectProperty extends PropertyGroup {
}
}

/**
* For some FHIR schemas, such as Extension, we need information from the url to limit creating associated value[x] fields.
* Enumerating all possible extension urls is kind of impossible task. The next best thing is to look for them in the value parameter.
* If value is null, create all possible value[x] as a fallback.
*
* @param value - Value of extension
*/
createPropertiesExtension(value: any) {
this.properties = {};
this.propertiesId = [];
const propList: string[] = value ? Object.keys(value) : this.schema.properties ? Object.keys(this.schema.properties) : [];
for (const propertyId of propList) {
if (this.schema.properties.hasOwnProperty(propertyId)) {
const propertySchema = this.schema.properties[propertyId];
if (propertySchema) {
this.properties[propertyId] = this.formPropertyFactory.createProperty(propertySchema, this, propertyId,
value ? value[propertyId] : null);
this.propertiesId.push(propertyId);
}
}
}
}

public _hasValue(): boolean {
return !!Object.keys(this.value).length;
}
Expand Down Expand Up @@ -98,8 +132,9 @@ PROPERTY_TYPE_MAPPING.object = (
parent: PropertyGroup,
path: string,
formPropertyFactory: FormPropertyFactory,
logger: LogService
logger: LogService,
value?: any
) => {
return new ObjectProperty(
formPropertyFactory, schemaValidatorFactory, validatorRegistry, expressionCompilerFactory, schema, parent, path, logger);
formPropertyFactory, schemaValidatorFactory, validatorRegistry, expressionCompilerFactory, schema, parent, path, logger, value);
};

0 comments on commit 5e66085

Please sign in to comment.