|
1 | | -import { UISchemaElement, ControlElement } from './models/uischema'; |
2 | | -import { JsonSchema } from './models/jsonSchema'; |
3 | | -import { getValuePropertyPair } from './path.util'; |
| 1 | +import {UISchemaElement} from './models/uischema'; |
| 2 | +import {JsonSchema} from './models/jsonSchema'; |
4 | 3 | import {UiSchemaRegistry, UiSchemaRegistryImpl} from './core/uischema.registry'; |
5 | | - |
6 | | -export enum RUNTIME_TYPE { |
7 | | - VALIDATION_ERROR, VISIBLE, ENABLED |
8 | | -} |
9 | | -export interface RuntimeListener { |
10 | | - notify(type: RUNTIME_TYPE); |
11 | | -} |
12 | | -export class Runtime { |
13 | | - private _validationErrors: Array<string> = []; |
14 | | - private _visible = true; |
15 | | - private _enabled = true; |
16 | | - private _listeners: Array<RuntimeListener> = []; |
17 | | - |
18 | | - get visible(): boolean {return this._visible; }; |
19 | | - get enabled(): boolean {return this._enabled; }; |
20 | | - get validationErrors(): Array<string> {return this._validationErrors; }; |
21 | | - |
22 | | - set visible(visible: boolean) { |
23 | | - this._visible = visible; |
24 | | - this.notifyListeners(RUNTIME_TYPE.VISIBLE); |
25 | | - }; |
26 | | - |
27 | | - set enabled(enabled: boolean) { |
28 | | - this._enabled = enabled; |
29 | | - this.notifyListeners(RUNTIME_TYPE.ENABLED); |
30 | | - }; |
31 | | - |
32 | | - set validationErrors(validationErrors: Array<string>) { |
33 | | - this._validationErrors = validationErrors; |
34 | | - this.notifyListeners(RUNTIME_TYPE.VALIDATION_ERROR); |
35 | | - }; |
36 | | - |
37 | | - addListener(listener: RuntimeListener): void { |
38 | | - this._listeners.push(listener); |
39 | | - } |
40 | | - |
41 | | - removeListener(listener: RuntimeListener): void { |
42 | | - this._listeners.splice(this._listeners.indexOf(listener), 1); |
43 | | - } |
44 | | - |
45 | | - private notifyListeners(type: RUNTIME_TYPE): void { |
46 | | - this._listeners.forEach(listener => listener.notify(type)); |
47 | | - } |
48 | | -} |
49 | | - |
50 | | -export abstract class Renderer extends HTMLElement implements RuntimeListener { |
51 | | - protected uischema: UISchemaElement; |
52 | | - protected dataService: DataService; |
53 | | - protected dataSchema: JsonSchema; |
54 | | - setUiSchema(uischema: UISchemaElement) { |
55 | | - this.uischema = uischema; |
56 | | - } |
57 | | - |
58 | | - setDataService(dataService: DataService) { |
59 | | - this.dataService = dataService; |
60 | | - } |
61 | | - |
62 | | - setDataSchema(dataSchema: JsonSchema) { |
63 | | - this.dataSchema = dataSchema; |
64 | | - } |
65 | | - |
66 | | - notify(type: RUNTIME_TYPE): void { |
67 | | - // |
68 | | - } |
69 | | - |
70 | | - connectedCallback(): void { |
71 | | - if (!this.uischema.hasOwnProperty('runtime')) { |
72 | | - const runtime = new Runtime(); |
73 | | - this.uischema['runtime'] = runtime; |
74 | | - } |
75 | | - const runtime = <Runtime>this.uischema['runtime']; |
76 | | - runtime.addListener(this); |
77 | | - this.render(); |
78 | | - } |
79 | | - disconnectedCallback(): void { |
80 | | - this.dispose(); |
81 | | - const runtime = <Runtime>this.uischema['runtime']; |
82 | | - runtime.removeListener(this); |
83 | | - } |
84 | | - |
85 | | - abstract render(): HTMLElement; |
86 | | - abstract dispose(): void; |
87 | | -} |
88 | | -export interface RendererTester { |
89 | | - (element: UISchemaElement, schema: JsonSchema): number; |
90 | | -} |
91 | | -class RendererService { |
92 | | - private renderers= []; |
93 | | - registerRenderer(tester: RendererTester, renderer: string): void { |
94 | | - this.renderers.push({tester: tester, renderer: renderer}); |
95 | | - } |
96 | | - unregisterRenderer(tester: RendererTester, renderer: string): void { |
97 | | - this.renderers.splice(this.renderers.indexOf({tester: tester, renderer: renderer}), 1); |
98 | | - } |
99 | | - getBestRenderer(uischema: UISchemaElement, |
100 | | - schema: JsonSchema, |
101 | | - dataService: DataService): HTMLElement { |
102 | | - let bestRenderer: string; |
103 | | - let specificity = -1; |
104 | | - this.renderers.forEach(renderer => { |
105 | | - const rSpec = renderer.tester(uischema, schema); |
106 | | - if (rSpec > specificity) { |
107 | | - bestRenderer = renderer.renderer; |
108 | | - specificity = rSpec; |
109 | | - } |
110 | | - }); |
111 | | - let renderer: HTMLElement; |
112 | | - if (bestRenderer === undefined) { |
113 | | - renderer = document.createElement('label'); |
114 | | - renderer.textContent = 'Unknown Schema: ' + JSON.stringify(uischema); |
115 | | - } else { |
116 | | - const cRenderer = <Renderer> document.createElement(bestRenderer); |
117 | | - cRenderer.setUiSchema(uischema); |
118 | | - cRenderer.setDataSchema(schema); |
119 | | - cRenderer.setDataService(dataService); |
120 | | - renderer = cRenderer; |
121 | | - } |
122 | | - return renderer; |
123 | | - } |
124 | | -} |
125 | | - |
126 | | -export interface DataChangeListener { |
127 | | - isRelevantKey: (uischema: ControlElement) => boolean; |
128 | | - notifyChange(uischema: ControlElement, newValue: any, data: any): void; |
129 | | -} |
130 | | -export class DataService { |
131 | | - private changeListeners: Array<DataChangeListener>= []; |
132 | | - constructor(private data: any) { |
133 | | - } |
134 | | - notifyChange(uischema: ControlElement, newValue: any): void { |
135 | | - const pair = getValuePropertyPair(this.data, uischema.scope.$ref); |
136 | | - if (Array.isArray(pair.instance[pair.property])) { |
137 | | - pair.instance[pair.property].push(newValue); |
138 | | - } else { |
139 | | - pair.instance[pair.property] = newValue; |
140 | | - } |
141 | | - |
142 | | - this.changeListeners.forEach(listener => { |
143 | | - if (listener.isRelevantKey(uischema)) { |
144 | | - listener.notifyChange(uischema, newValue, this.data); |
145 | | - } |
146 | | - }); |
147 | | - } |
148 | | - registerChangeListener(listener: DataChangeListener): void { |
149 | | - this.changeListeners.push(listener); |
150 | | - } |
151 | | - unregisterChangeListener(listener: DataChangeListener): void { |
152 | | - this.changeListeners.splice(this.changeListeners.indexOf(listener), 1); |
153 | | - } |
154 | | - getValue(uischema: ControlElement): any { |
155 | | - const pair = getValuePropertyPair(this.data, uischema.scope.$ref); |
156 | | - if (pair.property === undefined) { |
157 | | - return pair.instance; |
158 | | - } |
159 | | - return pair.instance[pair.property]; |
160 | | - } |
161 | | - initialRootRun(): void { |
162 | | - this.changeListeners.forEach(listener => { |
163 | | - if (listener.isRelevantKey(null)) { |
164 | | - listener.notifyChange(null, null, this.data); |
165 | | - } |
166 | | - }); |
167 | | - } |
168 | | -} |
| 4 | +import {DataService} from './core/data.service'; |
| 5 | +import {RendererService} from './core/renderer.service'; |
169 | 6 |
|
170 | 7 | export interface JsonFormService { |
171 | 8 | dispose(): void; |
|
0 commit comments