diff --git a/example/example.ts b/example/example.ts index 80a4493b9..73822def3 100644 --- a/example/example.ts +++ b/example/example.ts @@ -1,8 +1,6 @@ import {JsonSchema} from '../src/models/jsonSchema'; import {UISchemaElement} from '../src/models/uischema'; -import {JsonForms} from '../src/json-forms'; -import {Style} from '../src/core/styling.registry'; - +import {JsonFormsElement} from '../src/json-forms'; declare let exampleDivId; declare let viewDivId; @@ -32,7 +30,7 @@ export const changeExample = (selectedExample: string) => { body = div; } - const jsonForms = document.createElement('json-forms'); + const jsonForms = document.createElement('json-forms'); jsonForms.data = example.data; if (example.uiSchema !== undefined) { jsonForms.uiSchema = example.uiSchema; diff --git a/example/templates/day6.ts b/example/templates/day6.ts index a49d2430d..930099bcb 100644 --- a/example/templates/day6.ts +++ b/example/templates/day6.ts @@ -1,7 +1,7 @@ import {registerExamples} from '../example'; -import {JsonFormsHolder} from '../../src/core'; +import {JsonForms} from '../../src/core'; import {Renderer} from '../../src/core/renderer'; -import {JsonForms} from '../../src/json-forms'; +import {JsonFormsElement} from '../../src/json-forms'; import { resolveSchema } from '../../src/path.util'; import { UISchemaElement, ControlElement } from '../../src/models/uischema'; import { JsonSchema } from '../../src/models/jsonSchema'; @@ -114,7 +114,7 @@ const data = { }; const resetServices = () => { - const jsonforms = document.getElementsByTagName('json-forms')[0]; + const jsonforms = document.getElementsByTagName('json-forms')[0]; jsonforms.data = data; }; @@ -129,7 +129,7 @@ class MyControl extends Renderer { const span = document.createElement('span'); span.innerText = '\u2606'; span.onclick = () => { - this.dataService.notifyChange(controlElement, i); + this.dataService.notifyAboutDataChange(controlElement, i); this.updateSpans(span); }; span.onmouseover = () => { @@ -179,7 +179,7 @@ const setup = (div: HTMLDivElement) => { const buttonRegister = document.createElement('button'); buttonRegister.innerText = 'Register Custom Control'; buttonRegister.onclick = () => { - JsonFormsHolder.rendererService.registerRenderer(tester, 'my-control'); + JsonFormsElement.rendererService.registerRenderer(tester, 'my-control'); // HACK to retrigger service creation resetServices(); }; @@ -187,7 +187,7 @@ const setup = (div: HTMLDivElement) => { const buttonUnregister = document.createElement('button'); buttonUnregister.innerText = 'Unregister Custom Control'; buttonUnregister.onclick = () => { - JsonFormsHolder.rendererService.unregisterRenderer(tester, 'my-control'); + JsonFormsElement.rendererService.deregisterRenderer(tester, 'my-control'); // HACK to retrigger service creation resetServices(); }; diff --git a/example/templates/dynamic.ts b/example/templates/dynamic.ts index 09e15e45f..605ebc491 100644 --- a/example/templates/dynamic.ts +++ b/example/templates/dynamic.ts @@ -1,11 +1,11 @@ import {registerExamples} from '../example'; -import {JsonForms} from '../../src/json-forms'; +import {JsonFormsElement} from '../../src/json-forms'; const setup = (div: HTMLDivElement) => { const button = document.createElement('button'); button.innerText = 'Change data'; button.onclick = () => { - const jsonforms = document.getElementsByTagName('json-forms')[0]; + const jsonforms = document.getElementsByTagName('json-forms')[0]; jsonforms.data = {id: 'aaa'}; }; div.appendChild(button); diff --git a/example/templates/dynamic2.ts b/example/templates/dynamic2.ts index b2502feac..6c6dd02a0 100644 --- a/example/templates/dynamic2.ts +++ b/example/templates/dynamic2.ts @@ -1,8 +1,8 @@ -import { JsonFormService, JsonFormsHolder} from '../../src/core'; +import { JsonFormService, JsonForms} from '../../src/core'; import {DataService} from '../../src/core/data.service'; import { JsonSchema } from '../../src/models/jsonSchema'; import { UISchemaElement, ControlElement, Layout } from '../../src/models/uischema'; -import {JsonForms} from '../../src/json-forms'; +import {JsonFormsElement} from '../../src/json-forms'; import {registerExamples} from '../example'; @@ -17,7 +17,7 @@ class MyService implements JsonFormService { const button = document.createElement('button'); button.innerText = 'Change data'; button.onclick = () => { - this.dataService.notifyChange({type: 'Control', scope: {$ref: '#/properties/name'}}, 'blub'); + this.dataService.notifyAboutDataChange({type: 'Control', scope: {$ref: '#/properties/name'}}, 'blub'); }; const div = document.getElementById('dynamic2-example'); div.appendChild(button); @@ -25,7 +25,7 @@ class MyService implements JsonFormService { } const resetServices = () => { - const jsonforms = document.getElementsByTagName('json-forms')[0]; + const jsonforms = document.getElementsByTagName('json-forms')[0]; jsonforms.data = {name: 'bla'}; }; @@ -36,18 +36,18 @@ const setup = (div: HTMLDivElement) => { const buttonRegister = document.createElement('button'); buttonRegister.innerText = 'Register Service'; buttonRegister.onclick = () => { - JsonFormsHolder.jsonFormsServices.push(MyService); + JsonFormsElement.jsonFormsServices.push(MyService); resetServices(); }; div.appendChild(buttonRegister); const buttonUnregister = document.createElement('button'); buttonUnregister.innerText = 'Unregister Service'; buttonUnregister.onclick = () => { - const index = JsonFormsHolder.jsonFormsServices.indexOf(MyService); + const index = JsonFormsElement.jsonFormsServices.indexOf(MyService); if (index === -1) { return; } - JsonFormsHolder.jsonFormsServices.splice(index, 1); + JsonFormsElement.jsonFormsServices.splice(index, 1); // HACK to retrigger service creation resetServices(); dynamic2_example_div.removeChild(dynamic2_example_div.firstChild); diff --git a/example/templates/uischema-registry.ts b/example/templates/uischema-registry.ts index 34de8816d..824cb5673 100644 --- a/example/templates/uischema-registry.ts +++ b/example/templates/uischema-registry.ts @@ -1,6 +1,6 @@ import {registerExamples} from '../example'; -import {JsonFormsHolder} from '../../src/core'; -import {JsonForms} from '../../src/json-forms'; +import {JsonForms} from '../../src/core'; +import {JsonFormsElement} from '../../src/json-forms'; const uischema = { 'type': 'Group', @@ -18,24 +18,24 @@ const uischema = { const data = {name: 'John Doe'}; // HACK to retrigger service creation const resetServices = () => { - const jsonforms = document.getElementsByTagName('json-forms')[0]; + const jsonforms = document.getElementsByTagName('json-forms')[0]; jsonforms.data = data; }; const tester = (test_uischema, test_data) => 5; const setup = (div: HTMLDivElement) => { const registerButton = document.createElement('button'); registerButton.innerText = 'Register UI Schema'; - registerButton.className = JsonFormsHolder.stylingRegistry.getAsClassName('button'); + registerButton.className = JsonFormsElement.stylingRegistry.getAsClassName('button'); registerButton.onclick = () => { - JsonFormsHolder.uischemaRegistry.register(uischema, tester); + JsonFormsElement.uischemaRegistry.register(uischema, tester); resetServices(); }; div.appendChild(registerButton); const unregisterButton = document.createElement('button'); - unregisterButton.className = JsonFormsHolder.stylingRegistry.getAsClassName('button'); + unregisterButton.className = JsonFormsElement.stylingRegistry.getAsClassName('button'); unregisterButton.innerText = 'Unregister UI Schema'; unregisterButton.onclick = () => { - JsonFormsHolder.uischemaRegistry.unregister(uischema, tester); + JsonFormsElement.uischemaRegistry.deregister(uischema, tester); resetServices(); }; div.appendChild(unregisterButton); diff --git a/example_library/index.html b/example_library/index.html index 97cbabeaf..9a13bef40 100644 --- a/example_library/index.html +++ b/example_library/index.html @@ -43,7 +43,7 @@ const buttonUnregister = document.createElement('button'); buttonUnregister.innerText = 'Unregister Custom Control'; buttonUnregister.onclick = () => { - JSONForms.JsonFormsHolder.rendererService.unregisterRenderer(tester, 'custom-element'); + JSONForms.JsonFormsHolder.rendererService.deregisterRenderer(tester, 'custom-element'); // HACK to retrigger service creation resetServices(); }; diff --git a/src/core.ts b/src/core.ts index 95c73ee8b..1cc57ecf7 100644 --- a/src/core.ts +++ b/src/core.ts @@ -1,6 +1,6 @@ import {UISchemaElement} from './models/uischema'; import {JsonSchema} from './models/jsonSchema'; -import {UiSchemaRegistry, UiSchemaRegistryImpl} from './core/uischema.registry'; +import {UISchemaRegistry, UISchemaRegistryImpl} from './core/uischema.registry'; import {DataService} from './core/data.service'; import {RendererService} from './core/renderer.service'; import {StylingRegistry, StylingRegistryImpl} from './core/styling.registry'; @@ -36,15 +36,15 @@ export interface JsonFormsServiceConstructable { * @constructor */ export const JsonFormsServiceElement = (config) => (cls: JsonFormsServiceConstructable) => { - JsonFormsHolder.jsonFormsServices.push(cls); + JsonForms.jsonFormsServices.push(cls); }; /** * Global JSONForms object that holds services and registries. */ -export class JsonFormsHolder { +export class JsonForms { public static rendererService = new RendererService(); public static jsonFormsServices: Array = []; - public static uischemaRegistry: UiSchemaRegistry = new UiSchemaRegistryImpl(); + public static uischemaRegistry: UISchemaRegistry = new UISchemaRegistryImpl(); public static stylingRegistry: StylingRegistry = new StylingRegistryImpl(); } diff --git a/src/core/data.service.ts b/src/core/data.service.ts index d8565055f..266d7d364 100644 --- a/src/core/data.service.ts +++ b/src/core/data.service.ts @@ -8,21 +8,21 @@ export interface DataChangeListener { /** * Determines whether this listener is interested in any data change. - * If this returns true, the notifyChange method of the listener will be called. - * @param {ControlElement} uischema the control element that is affected by the data change + * If this returns true, the dataChanged method of the listener will be called. + * @param {ControlElement} uiSchema the control element that is affected by the data change * @returns whether this listener is interested in the given control element */ - isRelevantKey(uischema: ControlElement): boolean; + needsNotificationAbout(uiSchema: ControlElement): boolean; /** * Represents the listener's logic to be called in case of a data change that * is relevant to the listener. * - * @param {ControlElement} uischema the control element that is affected by the data change + * @param {ControlElement} controlElement the control element that is affected by the data change * @param {any} newValue the changed data value * @param {any} data the current data value */ - notifyChange(uischema: ControlElement, newValue: any, data: any): void; + dataChanged(controlElement: ControlElement, newValue: any, data: any): void; } /** @@ -30,7 +30,8 @@ export interface DataChangeListener { * a list of listeners that are notified whenever the data changes. */ export class DataService { - private changeListeners: Array= []; + + private dataChangeListeners: Array= []; /** * Constructor @@ -43,46 +44,41 @@ export class DataService { /** * Notifies any data change listeners about a data change. * - * @param {ControlElement} uischema the affected control element + * @param {ControlElement} controlElement the affected control element * @param newValue the new value of the data chunk */ - notifyChange(uischema: ControlElement, newValue: any): void { - if (uischema !== undefined && uischema !== null) { - const pair = getValuePropertyPair(this.data, uischema.scope.$ref); + notifyAboutDataChange(controlElement: ControlElement, newValue: any): void { + if (controlElement !== undefined && controlElement !== null) { + const pair = getValuePropertyPair(this.data, controlElement.scope.$ref); pair.instance[pair.property] = newValue; } - - this.changeListeners.forEach(listener => { - if (listener.isRelevantKey(uischema)) { - listener.notifyChange(uischema, newValue, this.data); - } - }); + this.notifyDataChangeListeners(controlElement, newValue); } /** * Register the given data change listener. * @param {DataChangeListener} listener the listener to be registered */ - registerChangeListener(listener: DataChangeListener): void { - this.changeListeners.push(listener); + registerDataChangeListener(listener: DataChangeListener): void { + this.dataChangeListeners.push(listener); } /** - * Un-register the given data change listener. + * De-register the given data change listener. * @param {DataChangeListener} listener the data change listener to be un-registered */ - unregisterChangeListener(listener: DataChangeListener): void { - this.changeListeners.splice(this.changeListeners.indexOf(listener), 1); + deregisterDataChangeListener(listener: DataChangeListener): void { + this.dataChangeListeners.splice(this.dataChangeListeners.indexOf(listener), 1); } /** * Resolve the ref of the given control against the root data. * - * @param {ControlElement} uischema + * @param {ControlElement} controlElement * @return {any} the de-referenced data chunk */ - getValue(uischema: ControlElement): any { - const pair = getValuePropertyPair(this.data, uischema.scope.$ref); + getValue(controlElement: ControlElement): any { + const pair = getValuePropertyPair(this.data, controlElement.scope.$ref); if (pair.property === undefined) { return pair.instance; } @@ -92,10 +88,14 @@ export class DataService { /** * Notifies all data change listeners initially. */ - initialRootRun(): void { - this.changeListeners.forEach(listener => { - if (listener.isRelevantKey(null)) { - listener.notifyChange(null, null, this.data); + initDataChangeListeners(): void { + this.notifyDataChangeListeners(null, null); + } + + private notifyDataChangeListeners(controlElement: ControlElement, newValue: any): void { + this.dataChangeListeners.forEach(listener => { + if (listener.needsNotificationAbout(controlElement)) { + listener.dataChanged(controlElement, newValue, this.data); } }); } diff --git a/src/core/renderer.service.ts b/src/core/renderer.service.ts index 3fc880241..9527b0a90 100644 --- a/src/core/renderer.service.ts +++ b/src/core/renderer.service.ts @@ -25,13 +25,14 @@ export class RendererService { } /** - * Unregister a renderer. + * Deregister a renderer. + * * @param {RankedTester} tester the tester of the renderer to be un-registered. * Note that strict equality is used when un-registering renderers. * @param {string} renderer the tag name of the HTML element that represents * the renderer to be un-registered */ - unregisterRenderer(tester: RankedTester, renderer: string): void { + deregisterRenderer(tester: RankedTester, renderer: string): void { this.renderers = _.filter(this.renderers, r => // compare testers via strict equality r.tester !== tester || !_.eq(r.renderer, renderer) @@ -40,24 +41,24 @@ export class RendererService { /** * Find the renderer that is capable of rendering the given UI schema. - * @param {UISchemaElement} uischema the UI schema to be rendered + * @param {UISchemaElement} uiSchema the UI schema to be rendered * @param {JsonSchema} schema the JSON data schema the associated data schema * @param {DataService} dataService the data service holding the data to be rendered * @return {HTMLElement} the rendered HTML element */ - getBestRenderer(uischema: UISchemaElement, - schema: JsonSchema, - dataService: DataService): HTMLElement { + findMostApplicableRenderer(uiSchema: UISchemaElement, + schema: JsonSchema, + dataService: DataService): HTMLElement { const bestRenderer = _.maxBy(this.renderers, renderer => - renderer.tester(uischema, schema) + renderer.tester(uiSchema, schema) ); if (bestRenderer === undefined) { const renderer = document.createElement('label'); - renderer.textContent = 'Unknown Schema: ' + JSON.stringify(uischema); + renderer.textContent = 'Unknown Schema: ' + JSON.stringify(uiSchema); return renderer; } else { const renderer = document.createElement(bestRenderer.renderer); - renderer.setUiSchema(uischema); + renderer.setUiSchema(uiSchema); renderer.setDataSchema(schema); renderer.setDataService(dataService); return renderer; diff --git a/src/core/renderer.ts b/src/core/renderer.ts index 328f931ed..75f9ae64f 100644 --- a/src/core/renderer.ts +++ b/src/core/renderer.ts @@ -54,7 +54,7 @@ export abstract class Renderer extends HTMLElement implements RuntimeListener { * * @param {RUNTIME_TYPE} type the type of runtime change */ - notify(type: RUNTIME_TYPE): void { + runtimeUpdated(type: RUNTIME_TYPE): void { // no-op } @@ -66,7 +66,7 @@ export abstract class Renderer extends HTMLElement implements RuntimeListener { this.uischema['runtime'] = new Runtime(); } const runtime = this.uischema['runtime']; - runtime.addListener(this); + runtime.registerRuntimeListener(this); this.render(); } @@ -76,7 +76,7 @@ export abstract class Renderer extends HTMLElement implements RuntimeListener { disconnectedCallback(): void { this.dispose(); const runtime = this.uischema['runtime']; - runtime.removeListener(this); + runtime.deregisterRuntimeListener(this); } /** diff --git a/src/core/runtime.ts b/src/core/runtime.ts index cbd4b7c1d..f577a7bf0 100644 --- a/src/core/runtime.ts +++ b/src/core/runtime.ts @@ -14,7 +14,7 @@ export interface RuntimeListener { * Called when a runtime related property changes. * @param {RUNTIME_TYPE} type the type of runtime change */ - notify(type: RUNTIME_TYPE): void; + runtimeUpdated(type: RUNTIME_TYPE): void; } /** @@ -52,7 +52,7 @@ export class Runtime { */ set visible(visible: boolean) { this._visible = visible; - this.notifyListeners(RUNTIME_TYPE.VISIBLE); + this.notifyRuntimeListeners(RUNTIME_TYPE.VISIBLE); }; /** @@ -61,7 +61,7 @@ export class Runtime { */ set enabled(enabled: boolean) { this._enabled = enabled; - this.notifyListeners(RUNTIME_TYPE.ENABLED); + this.notifyRuntimeListeners(RUNTIME_TYPE.ENABLED); }; /** @@ -71,7 +71,7 @@ export class Runtime { */ set validationErrors(validationErrors: Array) { this._validationErrors = validationErrors; - this.notifyListeners(RUNTIME_TYPE.VALIDATION_ERROR); + this.notifyRuntimeListeners(RUNTIME_TYPE.VALIDATION_ERROR); }; /** @@ -79,7 +79,7 @@ export class Runtime { * * @param {RuntimeListener} listener the runtime listener to be added */ - addListener(listener: RuntimeListener): void { + registerRuntimeListener(listener: RuntimeListener): void { this._listeners.push(listener); } @@ -88,7 +88,7 @@ export class Runtime { * * @param {RuntimeListener} listener the runtime listener to be removed */ - removeListener(listener: RuntimeListener): void { + deregisterRuntimeListener(listener: RuntimeListener): void { this._listeners.splice(this._listeners.indexOf(listener), 1); } @@ -97,7 +97,7 @@ export class Runtime { * * @param {RUNTIME_TYPE} type the runtime type */ - private notifyListeners(type: RUNTIME_TYPE): void { - this._listeners.forEach(listener => listener.notify(type)); + private notifyRuntimeListeners(type: RUNTIME_TYPE): void { + this._listeners.forEach(listener => listener.runtimeUpdated(type)); } } diff --git a/src/core/styling.registry.ts b/src/core/styling.registry.ts index 5e61b3fa5..e50b8a007 100644 --- a/src/core/styling.registry.ts +++ b/src/core/styling.registry.ts @@ -39,11 +39,11 @@ export interface StylingRegistry { registerMany(styles: Array