xt-components 0.5.5 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/xt-components.mjs +501 -325
- package/fesm2022/xt-components.mjs.map +1 -1
- package/index.d.ts +141 -66
- package/package.json +5 -1
|
@@ -1,11 +1,189 @@
|
|
|
1
|
+
import { isTypeReference, XtBaseTypeReference, xtTypeManager, ManagedDataHandler, isPrimitive } from 'xt-type';
|
|
1
2
|
import * as i0 from '@angular/core';
|
|
2
3
|
import { signal, computed, InjectionToken, inject, Injectable, input, model, output, viewChild, Component } from '@angular/core';
|
|
3
|
-
import { xtTypeManager, ManagedDataHandler, isPrimitive } from 'xt-type';
|
|
4
4
|
import { loadRemoteModule } from '@angular-architects/native-federation';
|
|
5
|
+
import { from, firstValueFrom } from 'rxjs';
|
|
5
6
|
import { NgComponentOutlet, CommonModule } from '@angular/common';
|
|
6
7
|
import * as i1 from '@angular/forms';
|
|
7
8
|
import { ReactiveFormsModule, FormControl, FormGroup, FormBuilder, FormArray } from '@angular/forms';
|
|
8
|
-
|
|
9
|
+
|
|
10
|
+
class XtPluginRegistry {
|
|
11
|
+
constructor() {
|
|
12
|
+
this.pluginRegistry = new Map();
|
|
13
|
+
this.componentRegistry = new Map();
|
|
14
|
+
this.componentByTypeCache = new Map();
|
|
15
|
+
this.actionByTypeRegistry = new Map();
|
|
16
|
+
this.listComponents = signal(new Array(), ...(ngDevMode ? [{ debugName: "listComponents" }] : []));
|
|
17
|
+
this.listPlugins = signal(new Array(), ...(ngDevMode ? [{ debugName: "listPlugins" }] : []));
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* The component can manage any standard javascript primitives types. That's usually the default whenever we don't know any particular type
|
|
21
|
+
* string
|
|
22
|
+
* number
|
|
23
|
+
* bigint
|
|
24
|
+
* boolean
|
|
25
|
+
* undefined
|
|
26
|
+
* null
|
|
27
|
+
* symbol is not managed
|
|
28
|
+
* Date, while an object and not a primitive, is managed
|
|
29
|
+
*/
|
|
30
|
+
static { this.ANY_PRIMITIVE_TYPE = "ANY_PRIMITIVE_TYPE"; }
|
|
31
|
+
/**
|
|
32
|
+
* The components can manage any composite javascript type. Default when no type has been defined and it's a user defined javascript object (not a data type)
|
|
33
|
+
*/
|
|
34
|
+
static { this.ANY_OBJECT_TYPE = "ANY_OBJECT_TYPE"; }
|
|
35
|
+
static { this.ANY_PRIMITIVE_SET = "ANY_PRIMITIVE_SET"; }
|
|
36
|
+
static { this.ANY_OBJECT_SET = "ANY_OBJECT_SET"; }
|
|
37
|
+
/**
|
|
38
|
+
* Whenever a component can handle any type of reference to a single entity or to multiple entities.
|
|
39
|
+
*/
|
|
40
|
+
static { this.ANY_SINGLE_REFERENCE = "ANY_SINGLE_REFERENCE"; }
|
|
41
|
+
static { this.ANY_MULTIPLE_REFERENCE = "ANY_MULTIPLE_REFERENCE"; }
|
|
42
|
+
registerPlugin(info) {
|
|
43
|
+
this.pluginRegistry.set(info.name, info);
|
|
44
|
+
if (info.components != null) {
|
|
45
|
+
let updated = false;
|
|
46
|
+
for (const comp of info.components) {
|
|
47
|
+
updated = true;
|
|
48
|
+
this.registerComponent(comp);
|
|
49
|
+
}
|
|
50
|
+
if (updated)
|
|
51
|
+
this.componentByTypeCache.clear(); // Force recalculation of type
|
|
52
|
+
}
|
|
53
|
+
if (info.actionHandlers != null) {
|
|
54
|
+
for (const handler of info.actionHandlers) {
|
|
55
|
+
this.registerActionHandler(handler);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
this.listPlugins.update((array) => {
|
|
59
|
+
let found = false;
|
|
60
|
+
for (let i = 0; i < array.length; i++) {
|
|
61
|
+
if (array[i].name == info.name) {
|
|
62
|
+
found = true;
|
|
63
|
+
array[i] = info;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (!found)
|
|
67
|
+
array.push(info);
|
|
68
|
+
return [...array]; // You have to send another value, not just update the existing one.
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
registerComponent(info) {
|
|
72
|
+
this.componentRegistry.set(info.componentName, info);
|
|
73
|
+
this.listComponents.update((array) => {
|
|
74
|
+
let found = false;
|
|
75
|
+
for (let i = 0; i < array.length; i++) {
|
|
76
|
+
if (array[i].componentName == info.componentName) {
|
|
77
|
+
found = true;
|
|
78
|
+
array[i] = info;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (!found)
|
|
82
|
+
array.push(info);
|
|
83
|
+
return array;
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
findComponentsForType(valueType, value) {
|
|
87
|
+
let originalType = valueType;
|
|
88
|
+
//console.debug('Finding type from '+valueType+' with value ',value);
|
|
89
|
+
// We don't know the value type, let's try to guess if it's a primitive or object based on the value
|
|
90
|
+
if (valueType == null) {
|
|
91
|
+
valueType = XtPluginRegistry.ANY_OBJECT_TYPE;
|
|
92
|
+
if ((value == null) || (typeof value != 'object')) {
|
|
93
|
+
valueType = XtPluginRegistry.ANY_PRIMITIVE_TYPE;
|
|
94
|
+
}
|
|
95
|
+
else if (value instanceof Date) {
|
|
96
|
+
valueType = XtPluginRegistry.ANY_PRIMITIVE_TYPE;
|
|
97
|
+
}
|
|
98
|
+
if (Array.isArray(value)) {
|
|
99
|
+
valueType = (valueType === XtPluginRegistry.ANY_PRIMITIVE_TYPE) ? XtPluginRegistry.ANY_PRIMITIVE_SET : XtPluginRegistry.ANY_OBJECT_SET;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
else { // originalType has been defined.
|
|
103
|
+
if (Array.isArray(value)) {
|
|
104
|
+
valueType = valueType.endsWith('[]') ? valueType : valueType + '[]';
|
|
105
|
+
originalType = valueType;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
//console.debug('Type found is '+valueType);
|
|
109
|
+
let ret = this.componentByTypeCache.get(valueType);
|
|
110
|
+
if (ret == null) {
|
|
111
|
+
ret = new Array();
|
|
112
|
+
for (const comp of this.componentRegistry) {
|
|
113
|
+
const info = comp[1];
|
|
114
|
+
if (info.typesHandled.includes(valueType)) {
|
|
115
|
+
ret.push(info);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if ((ret.length == 0) && (originalType != null)) {
|
|
119
|
+
// Couldn't find a specific component, let's try the generic ones, so we don't pass any type
|
|
120
|
+
ret = this.findComponentsForType(null, value);
|
|
121
|
+
// Cache the component only if we were able to assert its type.
|
|
122
|
+
// If no type has been given and value is null, then we cannot assess the real type
|
|
123
|
+
if (value != null) {
|
|
124
|
+
this.componentByTypeCache.set(originalType, ret);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
// Cache the component only if we were able to assert its type.
|
|
129
|
+
// If no type has been given and value is null, then we cannot assess the real type
|
|
130
|
+
if ((value != null) || (originalType != null)) {
|
|
131
|
+
this.componentByTypeCache.set(originalType ?? valueType, ret);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return ret;
|
|
136
|
+
}
|
|
137
|
+
static registry() {
|
|
138
|
+
return XT_REGISTRY;
|
|
139
|
+
}
|
|
140
|
+
findComponentInfo(type) {
|
|
141
|
+
// Search for the component registered with this class
|
|
142
|
+
for (const info of this.componentRegistry.values()) {
|
|
143
|
+
if (info.componentClass == type) {
|
|
144
|
+
return info;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
getComponentInfo(type) {
|
|
150
|
+
const ret = this.findComponentInfo(type);
|
|
151
|
+
if (ret == null) {
|
|
152
|
+
throw new Error("No component found with class " + type);
|
|
153
|
+
}
|
|
154
|
+
return ret;
|
|
155
|
+
}
|
|
156
|
+
registerActionHandler(handlerInfo) {
|
|
157
|
+
for (const type of handlerInfo.types) {
|
|
158
|
+
const handlers = handlerInfo.actions;
|
|
159
|
+
for (const actionName of Object.keys(handlers)) {
|
|
160
|
+
let exist = this.actionByTypeRegistry.get(type);
|
|
161
|
+
if (exist == null) {
|
|
162
|
+
exist = new Map();
|
|
163
|
+
this.actionByTypeRegistry.set(type, exist);
|
|
164
|
+
}
|
|
165
|
+
exist.set(actionName, handlers[actionName]);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
findActionInfo(type, actionName) {
|
|
170
|
+
const handlers = this.actionByTypeRegistry.get(type);
|
|
171
|
+
if (handlers != null) {
|
|
172
|
+
return handlers.get(actionName);
|
|
173
|
+
}
|
|
174
|
+
return undefined;
|
|
175
|
+
}
|
|
176
|
+
listActionInfos(type) {
|
|
177
|
+
const handlers = this.actionByTypeRegistry.get(type);
|
|
178
|
+
if (handlers != null) {
|
|
179
|
+
return Array.from(handlers.entries()).map(([name, info]) => {
|
|
180
|
+
return { name: name, info: info };
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
else
|
|
184
|
+
return [];
|
|
185
|
+
}
|
|
186
|
+
}
|
|
9
187
|
|
|
10
188
|
class XtBaseContext {
|
|
11
189
|
/**
|
|
@@ -17,6 +195,11 @@ class XtBaseContext {
|
|
|
17
195
|
*/
|
|
18
196
|
constructor(displayMode, subName, parentGroup, parentContext) {
|
|
19
197
|
this.displayMode = 'FULL_VIEW';
|
|
198
|
+
/**
|
|
199
|
+
* If it's a reference, we keep the context referenced
|
|
200
|
+
*
|
|
201
|
+
referencedContext?:XtContext<any>;*/
|
|
202
|
+
//subReferencesResolved = signal(false);
|
|
20
203
|
/**
|
|
21
204
|
* Keeps track of all the possible actions for this context
|
|
22
205
|
* @protected
|
|
@@ -77,7 +260,7 @@ class XtBaseContext {
|
|
|
77
260
|
return this;
|
|
78
261
|
}
|
|
79
262
|
isInForm() {
|
|
80
|
-
return (
|
|
263
|
+
return (this.formGroup() != null);
|
|
81
264
|
}
|
|
82
265
|
formControlNameOrNull() {
|
|
83
266
|
return this.subName ?? null;
|
|
@@ -168,11 +351,18 @@ class XtBaseContext {
|
|
|
168
351
|
if (!Array.isArray(this.value())) {
|
|
169
352
|
throw new Error("The value must be an Array / Set to create a subElement context.");
|
|
170
353
|
}
|
|
171
|
-
const
|
|
172
|
-
ret.
|
|
173
|
-
if (
|
|
174
|
-
|
|
175
|
-
ret.
|
|
354
|
+
const indexKey = elementIndex.toString();
|
|
355
|
+
let ret = this.childContexts?.get(indexKey);
|
|
356
|
+
if (ret == null) {
|
|
357
|
+
ret = new XtBaseContext(this.displayMode, undefined, undefined, this);
|
|
358
|
+
ret.setDisplayValue(value[elementIndex]);
|
|
359
|
+
if (this.valueType != null) {
|
|
360
|
+
// Convert potential array type into single type
|
|
361
|
+
ret.valueType = this.valueType.endsWith('[]') ? this.valueType.substring(0, this.valueType.length - 2) : this.valueType;
|
|
362
|
+
}
|
|
363
|
+
if (this.childContexts == null)
|
|
364
|
+
this.childContexts = new Map();
|
|
365
|
+
this.childContexts?.set(indexKey, ret);
|
|
176
366
|
}
|
|
177
367
|
return ret;
|
|
178
368
|
}
|
|
@@ -205,7 +395,25 @@ class XtBaseContext {
|
|
|
205
395
|
ret.valueType = subType;
|
|
206
396
|
}
|
|
207
397
|
else if ((this.valueType != null) && (typeResolver != null)) {
|
|
208
|
-
|
|
398
|
+
const subType = typeResolver.findType(this.valueType, subName, this.value());
|
|
399
|
+
if (subType != null) {
|
|
400
|
+
if (isTypeReference(subType)) {
|
|
401
|
+
if (subType.type == XtBaseTypeReference.UNRESOLVED_TYPE)
|
|
402
|
+
throw new Error("You must resolve all reference types before using them in a context. Missing type " + subType.type + " for subName " + subName + " in valueType " + this.valueType + " of context " + this.toString());
|
|
403
|
+
ret.valueType = subType.toType;
|
|
404
|
+
ret.reference = subType;
|
|
405
|
+
if (this.displayMode == 'LIST_VIEW')
|
|
406
|
+
ret.displayMode = 'INLINE_VIEW'; // We display a reference as inline in a list
|
|
407
|
+
else if (this.displayMode == 'FULL_EDITABLE') {
|
|
408
|
+
// We don't edit directly references, we simply enable selection of them.
|
|
409
|
+
ret.valueType = (subType.referenceType == 'ONE-TO-MANY') ? XtPluginRegistry.ANY_MULTIPLE_REFERENCE : XtPluginRegistry.ANY_SINGLE_REFERENCE;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
else {
|
|
413
|
+
ret.valueType = subType.type;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
//ret.valueType=typeResolver.findTypeName(this.valueType, subName, this.value())??undefined;
|
|
209
417
|
}
|
|
210
418
|
if (this.childContexts == null)
|
|
211
419
|
this.childContexts = new Map();
|
|
@@ -216,6 +424,28 @@ class XtBaseContext {
|
|
|
216
424
|
formGroup() {
|
|
217
425
|
return this.localFormGroup ?? this.parentFormGroup;
|
|
218
426
|
}
|
|
427
|
+
isReference() {
|
|
428
|
+
return (this.reference != null);
|
|
429
|
+
}
|
|
430
|
+
setReferenceInfo(reference) {
|
|
431
|
+
this.reference = reference;
|
|
432
|
+
//this.subReferencesResolved.set(this.reference!=null);
|
|
433
|
+
}
|
|
434
|
+
/**
|
|
435
|
+
* creates the referencedContext by using this referenced value
|
|
436
|
+
* @param val
|
|
437
|
+
*
|
|
438
|
+
updateReferencedContext(val: any, valueType?:string): void {
|
|
439
|
+
if (!this.isReference()) throw new Error ('This context '+this.toString()+' is not a reference.');
|
|
440
|
+
|
|
441
|
+
if( this.referencedContext==null) {
|
|
442
|
+
let refDisplayMode = 'INLINE_VIEW' as XtDisplayMode;
|
|
443
|
+
if (this.displayMode=='FULL_VIEW') refDisplayMode = 'FULL_VIEW';
|
|
444
|
+
this.referencedContext = new XtBaseContext(refDisplayMode);
|
|
445
|
+
}
|
|
446
|
+
this.referencedContext.setDisplayValue(val);
|
|
447
|
+
if( valueType!=null) this.referencedContext.valueType=valueType;
|
|
448
|
+
}*/
|
|
219
449
|
toString() {
|
|
220
450
|
let ret = 'XtContext named ';
|
|
221
451
|
ret += this.subName ?? 'None';
|
|
@@ -223,6 +453,10 @@ class XtBaseContext {
|
|
|
223
453
|
ret += this.valueType ?? 'None';
|
|
224
454
|
ret += ' with value ';
|
|
225
455
|
ret += this.nonFormValue ? this.nonFormValue() : this.formControlValue();
|
|
456
|
+
if (this.isReference()) {
|
|
457
|
+
ret += ' referencing ';
|
|
458
|
+
ret += this.reference?.type;
|
|
459
|
+
}
|
|
226
460
|
return ret;
|
|
227
461
|
}
|
|
228
462
|
}
|
|
@@ -242,225 +476,221 @@ class XtResolvedComponent {
|
|
|
242
476
|
}
|
|
243
477
|
}
|
|
244
478
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
this.listPlugins = signal(new Array(), ...(ngDevMode ? [{ debugName: "listPlugins" }] : []));
|
|
479
|
+
/**
|
|
480
|
+
* The global plugin registry.
|
|
481
|
+
* Plugins will register to this when loaded.
|
|
482
|
+
*/
|
|
483
|
+
function initXtPluginRegistry() {
|
|
484
|
+
if (globalThis.XT_REGISTRY == null) {
|
|
485
|
+
globalThis.XT_REGISTRY = new XtPluginRegistry();
|
|
253
486
|
}
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
* bigint
|
|
259
|
-
* boolean
|
|
260
|
-
* undefined
|
|
261
|
-
* null
|
|
262
|
-
* symbol is not managed
|
|
263
|
-
* Date, while an object and not a primitive, is managed
|
|
264
|
-
*/
|
|
265
|
-
static { this.ANY_PRIMITIVE_TYPE = "ANY_PRIMITIVE_TYPE"; }
|
|
266
|
-
/**
|
|
267
|
-
* The components can manage any composite javascript type. Default when no type has been defined and it's a user defined javascript object (not a data type)
|
|
268
|
-
*/
|
|
269
|
-
static { this.ANY_OBJECT_TYPE = "ANY_OBJECT_TYPE"; }
|
|
270
|
-
static { this.ANY_PRIMITIVE_SET = "ANY_PRIMITIVE_SET"; }
|
|
271
|
-
static { this.ANY_OBJECT_SET = "ANY_OBJECT_SET"; }
|
|
272
|
-
registerPlugin(info) {
|
|
273
|
-
this.pluginRegistry.set(info.name, info);
|
|
274
|
-
if (info.components != null) {
|
|
275
|
-
let updated = false;
|
|
276
|
-
for (const comp of info.components) {
|
|
277
|
-
updated = true;
|
|
278
|
-
this.registerComponent(comp);
|
|
279
|
-
}
|
|
280
|
-
if (updated)
|
|
281
|
-
this.componentByTypeCache.clear(); // Force recalculation of type
|
|
282
|
-
}
|
|
283
|
-
if (info.actionHandlers != null) {
|
|
284
|
-
for (const handler of info.actionHandlers) {
|
|
285
|
-
this.registerActionHandler(handler);
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
this.listPlugins.update((array) => {
|
|
289
|
-
let found = false;
|
|
290
|
-
for (let i = 0; i < array.length; i++) {
|
|
291
|
-
if (array[i].name == info.name) {
|
|
292
|
-
found = true;
|
|
293
|
-
array[i] = info;
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
if (!found)
|
|
297
|
-
array.push(info);
|
|
298
|
-
return [...array]; // You have to send another value, not just update the existing one.
|
|
299
|
-
});
|
|
487
|
+
}
|
|
488
|
+
function xtPluginRegistry() {
|
|
489
|
+
if (globalThis.XT_REGISTRY == null) {
|
|
490
|
+
initXtPluginRegistry();
|
|
300
491
|
}
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
if (!found)
|
|
312
|
-
array.push(info);
|
|
313
|
-
return array;
|
|
314
|
-
});
|
|
492
|
+
return globalThis.XT_REGISTRY;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
const XT_RESOLVER_TOKEN = new InjectionToken('Enable providing a custom component resolver.');
|
|
496
|
+
const XT_TYPE_RESOLVER_TOKEN = new InjectionToken('Enable providing a custom type resolver.');
|
|
497
|
+
const XT_REGISTRY_TOKEN = new InjectionToken("Injects the Plugin Registry right into your angular component", {
|
|
498
|
+
factory: () => {
|
|
499
|
+
return xtPluginRegistry();
|
|
315
500
|
}
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
501
|
+
});
|
|
502
|
+
|
|
503
|
+
class XtRegistryResolver {
|
|
504
|
+
constructor(registry, typeResolver) {
|
|
505
|
+
this.registry = registry;
|
|
506
|
+
this.typeResolver = typeResolver;
|
|
507
|
+
}
|
|
508
|
+
resolve(baseContext, subName) {
|
|
509
|
+
let typeToFind = baseContext.valueType;
|
|
510
|
+
const typeInfo = this.typeResolver.findType(baseContext.valueType, subName);
|
|
511
|
+
// If it's a type reference, we find the component of the referenced type
|
|
512
|
+
if (isTypeReference(typeInfo)) {
|
|
513
|
+
if (baseContext.displayMode == 'FULL_EDITABLE') {
|
|
514
|
+
typeToFind = XtPluginRegistry.ANY_SINGLE_REFERENCE;
|
|
327
515
|
}
|
|
328
|
-
|
|
329
|
-
|
|
516
|
+
else {
|
|
517
|
+
typeToFind = typeInfo.toType;
|
|
330
518
|
}
|
|
331
519
|
}
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
originalType = valueType;
|
|
336
|
-
}
|
|
520
|
+
const ret = this.registry.findComponentsForType(typeToFind, baseContext.subValue(subName));
|
|
521
|
+
if (ret != null && ret.length > 0) {
|
|
522
|
+
return XtResolvedComponent.from(ret[0]);
|
|
337
523
|
}
|
|
338
|
-
|
|
339
|
-
|
|
524
|
+
return null;
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
class XtAction {
|
|
529
|
+
constructor(name, info, enabled) {
|
|
530
|
+
this.enabled = signal(false, ...(ngDevMode ? [{ debugName: "enabled" }] : []));
|
|
531
|
+
this.name = name;
|
|
532
|
+
this.info = info;
|
|
533
|
+
if (enabled != null) {
|
|
534
|
+
this.enabled.set(enabled);
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
/**
|
|
540
|
+
* A very light and not 100% compatible storemanager in case you are not using xt-store.
|
|
541
|
+
* It can emulate XtStoreManager to some extends for doing some tests
|
|
542
|
+
*/
|
|
543
|
+
class StoreTestHelper {
|
|
544
|
+
static ensureTestProviderOnly() {
|
|
545
|
+
StoreSupport.setTestStoreManager(new TestStoreManager());
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
class TestStoreManager {
|
|
549
|
+
constructor() {
|
|
550
|
+
this.defaultProvider = new TestStoreProvider();
|
|
551
|
+
}
|
|
552
|
+
getProvider(name) {
|
|
553
|
+
return this.defaultProvider;
|
|
554
|
+
}
|
|
555
|
+
getProviderSafe(name) {
|
|
556
|
+
return this.defaultProvider;
|
|
557
|
+
}
|
|
558
|
+
getDefaultProvider() {
|
|
559
|
+
return this.defaultProvider;
|
|
560
|
+
}
|
|
561
|
+
getDefaultProviderSafe() {
|
|
562
|
+
return this.defaultProvider;
|
|
563
|
+
}
|
|
564
|
+
newStoreCriteria(name, value, operator) {
|
|
565
|
+
return new TestStoreCriteria(name, value, operator);
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
class TestStoreProvider {
|
|
569
|
+
constructor() {
|
|
570
|
+
this.data = new Map();
|
|
571
|
+
}
|
|
572
|
+
getOrCreateArray(name) {
|
|
573
|
+
let ret = this.data.get(name);
|
|
340
574
|
if (ret == null) {
|
|
341
|
-
ret = new
|
|
342
|
-
|
|
343
|
-
const info = comp[1];
|
|
344
|
-
if (info.typesHandled.includes(valueType)) {
|
|
345
|
-
ret.push(info);
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
if ((ret.length == 0) && (originalType != null)) {
|
|
349
|
-
// Couldn't find a specific component, let's try the generic ones, so we don't pass any type
|
|
350
|
-
ret = this.findComponentsForType(null, value);
|
|
351
|
-
// Cache the component only if we were able to assert its type.
|
|
352
|
-
// If no type has been given and value is null, then we cannot assess the real type
|
|
353
|
-
if (value != null) {
|
|
354
|
-
this.componentByTypeCache.set(originalType, ret);
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
else {
|
|
358
|
-
// Cache the component only if we were able to assert its type.
|
|
359
|
-
// If no type has been given and value is null, then we cannot assess the real type
|
|
360
|
-
if ((value != null) || (originalType != null)) {
|
|
361
|
-
this.componentByTypeCache.set(originalType ?? valueType, ret);
|
|
362
|
-
}
|
|
363
|
-
}
|
|
575
|
+
ret = new Map();
|
|
576
|
+
this.data.set(name, ret);
|
|
364
577
|
}
|
|
365
578
|
return ret;
|
|
366
579
|
}
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
if (
|
|
374
|
-
|
|
580
|
+
extractKey(value, create) {
|
|
581
|
+
if (value._id != null)
|
|
582
|
+
return value._id; // ManagedData key
|
|
583
|
+
else if (value.id != null)
|
|
584
|
+
return value.id;
|
|
585
|
+
else {
|
|
586
|
+
if (create === true) {
|
|
587
|
+
const newId = Math.random().toString(36).substring(2, 8);
|
|
588
|
+
value._id = newId;
|
|
589
|
+
return newId;
|
|
375
590
|
}
|
|
591
|
+
return value.toString();
|
|
376
592
|
}
|
|
377
|
-
return null;
|
|
378
593
|
}
|
|
379
|
-
|
|
380
|
-
|
|
594
|
+
storeEntity(name, entity) {
|
|
595
|
+
this.getOrCreateArray(name).set(this.extractKey(entity, true), entity);
|
|
596
|
+
return Promise.resolve(entity);
|
|
597
|
+
}
|
|
598
|
+
safeLoadEntity(name, key) {
|
|
599
|
+
const ret = this.getOrCreateArray(name).get(key);
|
|
381
600
|
if (ret == null) {
|
|
382
|
-
throw new Error("No
|
|
601
|
+
throw new Error("No entity named " + name + " with key " + key);
|
|
383
602
|
}
|
|
384
|
-
return ret;
|
|
603
|
+
return Promise.resolve(ret);
|
|
385
604
|
}
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
605
|
+
loadEntity(name, key) {
|
|
606
|
+
return Promise.resolve(this.getOrCreateArray(name).get(key));
|
|
607
|
+
}
|
|
608
|
+
deleteEntity(name, key) {
|
|
609
|
+
return Promise.resolve(this.getOrCreateArray(name).delete(key));
|
|
610
|
+
}
|
|
611
|
+
searchEntities(name, ...criteria) {
|
|
612
|
+
// No criteria defined, just send the full list
|
|
613
|
+
const ret = new Array();
|
|
614
|
+
if ((criteria == null) || (criteria.length == 0)) {
|
|
615
|
+
for (const toAdd of this.getOrCreateArray(name).values()) {
|
|
616
|
+
ret.push(toAdd);
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
else {
|
|
620
|
+
for (const toAdd of this.getOrCreateArray(name).values()) {
|
|
621
|
+
let canAdd = true;
|
|
622
|
+
for (const criter of criteria) {
|
|
623
|
+
if (!criter.filter(toAdd)) {
|
|
624
|
+
canAdd = false;
|
|
625
|
+
break;
|
|
626
|
+
}
|
|
394
627
|
}
|
|
395
|
-
|
|
628
|
+
if (canAdd)
|
|
629
|
+
ret.push(toAdd);
|
|
396
630
|
}
|
|
397
631
|
}
|
|
632
|
+
return from([ret]);
|
|
398
633
|
}
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
if (handlers != null) {
|
|
402
|
-
return handlers.get(actionName);
|
|
403
|
-
}
|
|
404
|
-
return undefined;
|
|
634
|
+
searchAndPrepareEntities(name, sort, groupBy, transformer, ...criteria) {
|
|
635
|
+
throw new Error('Method not implemented.');
|
|
405
636
|
}
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
if (handlers != null) {
|
|
409
|
-
return Array.from(handlers.entries()).map(([name, info]) => {
|
|
410
|
-
return { name: name, info: info };
|
|
411
|
-
});
|
|
412
|
-
}
|
|
413
|
-
else
|
|
414
|
-
return [];
|
|
637
|
+
canStoreDocument() {
|
|
638
|
+
return true;
|
|
415
639
|
}
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
* The global plugin registry.
|
|
420
|
-
* Plugins will register to this when loaded.
|
|
421
|
-
*/
|
|
422
|
-
function initXtPluginRegistry() {
|
|
423
|
-
if (globalThis.XT_REGISTRY == null) {
|
|
424
|
-
globalThis.XT_REGISTRY = new XtPluginRegistry();
|
|
640
|
+
storeDocument(toStore) {
|
|
641
|
+
const ret = new TestDocumentInfo(toStore.name, true, URL.createObjectURL(toStore));
|
|
642
|
+
return Promise.resolve(ret);
|
|
425
643
|
}
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
if (globalThis.XT_REGISTRY == null) {
|
|
429
|
-
initXtPluginRegistry();
|
|
644
|
+
storeDocuments(toStore) {
|
|
645
|
+
throw new Error('Method not implemented.');
|
|
430
646
|
}
|
|
431
|
-
return globalThis.XT_REGISTRY;
|
|
432
647
|
}
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
return xtPluginRegistry();
|
|
648
|
+
class TestDocumentInfo {
|
|
649
|
+
constructor(documentName, isUrl, documentId) {
|
|
650
|
+
this.documentId = documentId;
|
|
651
|
+
this.documentName = documentName;
|
|
652
|
+
this.isUrl = isUrl;
|
|
439
653
|
}
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
this.
|
|
445
|
-
|
|
654
|
+
}
|
|
655
|
+
class TestStoreCriteria {
|
|
656
|
+
constructor(name, value, operator) {
|
|
657
|
+
this.name = name;
|
|
658
|
+
this.value = value;
|
|
659
|
+
if (!operator)
|
|
660
|
+
this.operator = '=';
|
|
661
|
+
else {
|
|
662
|
+
this.operator = operator;
|
|
663
|
+
}
|
|
446
664
|
}
|
|
447
|
-
|
|
448
|
-
const
|
|
449
|
-
|
|
450
|
-
|
|
665
|
+
filter(toFilter) {
|
|
666
|
+
const testValue = toFilter[this.name];
|
|
667
|
+
switch (this.operator) {
|
|
668
|
+
case '=':
|
|
669
|
+
return testValue == this.value;
|
|
670
|
+
case '<':
|
|
671
|
+
return testValue < this.value;
|
|
672
|
+
case '<=':
|
|
673
|
+
return testValue < this.value;
|
|
674
|
+
default:
|
|
675
|
+
return true;
|
|
451
676
|
}
|
|
452
|
-
return null;
|
|
453
677
|
}
|
|
454
678
|
}
|
|
455
679
|
|
|
456
|
-
class
|
|
457
|
-
|
|
458
|
-
this.
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
680
|
+
class StoreSupport {
|
|
681
|
+
static isStoreManagerAvailable() {
|
|
682
|
+
if (this.testStoreManager != null)
|
|
683
|
+
return true;
|
|
684
|
+
return (globalThis.xtStoreManager != undefined);
|
|
685
|
+
}
|
|
686
|
+
static getStoreManager() {
|
|
687
|
+
return this.testStoreManager ?? (globalThis.xtStoreManager());
|
|
688
|
+
}
|
|
689
|
+
static setTestStoreManager(testStoreManager) {
|
|
690
|
+
StoreSupport.testStoreManager = testStoreManager;
|
|
691
|
+
}
|
|
692
|
+
static newStoreCriteria(name, value, operator) {
|
|
693
|
+
return new TestStoreCriteria(name, value, operator);
|
|
464
694
|
}
|
|
465
695
|
}
|
|
466
696
|
|
|
@@ -501,7 +731,13 @@ class XtResolverService {
|
|
|
501
731
|
return ret;
|
|
502
732
|
}
|
|
503
733
|
findTypeHandlerOf(baseContext, subName, value) {
|
|
504
|
-
|
|
734
|
+
let ret = { typeName: undefined, handler: undefined };
|
|
735
|
+
if (baseContext.isReference()) {
|
|
736
|
+
ret = this.typeResolver.findTypeHandler(baseContext.reference.toType, false, undefined, value);
|
|
737
|
+
}
|
|
738
|
+
else {
|
|
739
|
+
ret = this.typeResolver.findTypeHandler(baseContext.valueType, false, subName, value);
|
|
740
|
+
}
|
|
505
741
|
return ret;
|
|
506
742
|
}
|
|
507
743
|
listSubNamesOf(baseContext, value) {
|
|
@@ -657,6 +893,41 @@ class XtResolverService {
|
|
|
657
893
|
}
|
|
658
894
|
return undefined;
|
|
659
895
|
}
|
|
896
|
+
async resolveReferencedValue(context, storeMgr) {
|
|
897
|
+
if (!context.isReference())
|
|
898
|
+
return undefined;
|
|
899
|
+
const ref = context.reference;
|
|
900
|
+
const storeProvider = storeMgr.getProvider(ref.type);
|
|
901
|
+
if (storeProvider == null) {
|
|
902
|
+
throw new Error('No Store provider found for type ' + ref.type);
|
|
903
|
+
}
|
|
904
|
+
const ret = await firstValueFrom(storeProvider.searchEntities(ref.toType, storeMgr.newStoreCriteria(ref.field, context.value(), '=')));
|
|
905
|
+
if (ret.length == 0)
|
|
906
|
+
return null;
|
|
907
|
+
if (ref.referenceType == 'MANY-TO-ONE') {
|
|
908
|
+
if (ret.length > 1)
|
|
909
|
+
throw new Error('Multiple values for many to one relation between ' + context.valueType + ' and ' + ref.type + ' with value ' + context.value());
|
|
910
|
+
return ret[0];
|
|
911
|
+
}
|
|
912
|
+
else if (ref.referenceType == 'ONE-TO-MANY') {
|
|
913
|
+
return ret;
|
|
914
|
+
}
|
|
915
|
+
return undefined;
|
|
916
|
+
}
|
|
917
|
+
resolvePendingReferences() {
|
|
918
|
+
this.typeResolver.resolveAllTypeReferences();
|
|
919
|
+
}
|
|
920
|
+
/**
|
|
921
|
+
* Calculates the values that can be referenced by the reference & value of this context
|
|
922
|
+
* @param context
|
|
923
|
+
*/
|
|
924
|
+
findPossibleReferences(context) {
|
|
925
|
+
if (!context.isReference())
|
|
926
|
+
throw new Error('Cannot find possible references of this non reference context' + context.toString());
|
|
927
|
+
const reference = context.reference;
|
|
928
|
+
const store = StoreSupport.getStoreManager().getProviderSafe(reference.toType);
|
|
929
|
+
return store.searchEntities(reference.toType);
|
|
930
|
+
}
|
|
660
931
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: XtResolverService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
661
932
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: XtResolverService, providedIn: 'root' }); }
|
|
662
933
|
}
|
|
@@ -694,6 +965,10 @@ class XtRenderComponent {
|
|
|
694
965
|
let form = this.formGroup();
|
|
695
966
|
const ret = new XtBaseContext(this.displayMode(), this.subName(), form);
|
|
696
967
|
ret.valueType = this.valueType();
|
|
968
|
+
const typeInfo = this.resolverService.typeResolver.findType(ret.valueType);
|
|
969
|
+
if (isTypeReference(typeInfo)) {
|
|
970
|
+
ret.setReferenceInfo(typeInfo);
|
|
971
|
+
}
|
|
697
972
|
if (!ret.isInForm()) {
|
|
698
973
|
const subName = this.subName();
|
|
699
974
|
const value = this.value();
|
|
@@ -706,6 +981,13 @@ class XtRenderComponent {
|
|
|
706
981
|
}
|
|
707
982
|
return ret;
|
|
708
983
|
}, ...(ngDevMode ? [{ debugName: "context" }] : []));
|
|
984
|
+
this.realContext = computed(() => {
|
|
985
|
+
let ret = this.context();
|
|
986
|
+
/*if ((ret.isReference())&& (ret.referencedContext!=null)) {
|
|
987
|
+
ret = ret.referencedContext;
|
|
988
|
+
}*/
|
|
989
|
+
return ret;
|
|
990
|
+
}, ...(ngDevMode ? [{ debugName: "realContext" }] : []));
|
|
709
991
|
this.type = computed(() => {
|
|
710
992
|
//console.debug("Calculating type in XtRenderSubComponent");
|
|
711
993
|
let type = this.componentType();
|
|
@@ -714,7 +996,7 @@ class XtRenderComponent {
|
|
|
714
996
|
//console.debug('XtRender, using component set '+ type);
|
|
715
997
|
//compFound = this.resolverService.findComponentInfo (type);
|
|
716
998
|
//} else {
|
|
717
|
-
compFound = this.resolverService.findBestComponent(this.
|
|
999
|
+
compFound = this.resolverService.findBestComponent(this.realContext());
|
|
718
1000
|
//console.debug('XtRender, found component ',compFound.componentName);
|
|
719
1001
|
type = compFound.componentClass;
|
|
720
1002
|
}
|
|
@@ -767,6 +1049,13 @@ class XtRenderSubComponent {
|
|
|
767
1049
|
this.outputs = output();
|
|
768
1050
|
this.outlet = viewChild.required(NgComponentOutlet);
|
|
769
1051
|
this.resolverService = inject(XtResolverService);
|
|
1052
|
+
this.realContext = computed(() => {
|
|
1053
|
+
let ret = this.context();
|
|
1054
|
+
/*if ((ret.isReference()) && (ret.referencedContext!=null)) {
|
|
1055
|
+
ret = ret.referencedContext;
|
|
1056
|
+
}*/
|
|
1057
|
+
return ret;
|
|
1058
|
+
}, ...(ngDevMode ? [{ debugName: "realContext" }] : []));
|
|
770
1059
|
this.type = computed(() => {
|
|
771
1060
|
//console.debug("Calculating type in XtRenderSubComponent");
|
|
772
1061
|
let type = this.componentType();
|
|
@@ -775,7 +1064,7 @@ class XtRenderSubComponent {
|
|
|
775
1064
|
//console.debug('XtRender, using component set '+ type);
|
|
776
1065
|
//compFound = this.resolverService.findComponentInfo (type);
|
|
777
1066
|
//} else {
|
|
778
|
-
compFound = this.resolverService.findBestComponent(this.
|
|
1067
|
+
compFound = this.resolverService.findBestComponent(this.realContext());
|
|
779
1068
|
//console.debug('XtRender, found component ',compFound.componentName);
|
|
780
1069
|
type = compFound.componentClass;
|
|
781
1070
|
}
|
|
@@ -805,14 +1094,14 @@ class XtRenderSubComponent {
|
|
|
805
1094
|
}
|
|
806
1095
|
}
|
|
807
1096
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: XtRenderSubComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
808
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "20.3.9", type: XtRenderSubComponent, isStandalone: true, selector: "xt-render-sub", inputs: { context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: true, transformFunction: null }, componentType: { classPropertyName: "componentType", publicName: "componentType", isSignal: true, isRequired: false, transformFunction: null }, inputs: { classPropertyName: "inputs", publicName: "inputs", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { outputs: "outputs" }, viewQueries: [{ propertyName: "outlet", first: true, predicate: NgComponentOutlet, descendants: true, isSignal: true }], ngImport: i0, template: "{{componentType()}}\n<ng-container *ngComponentOutlet=\"type(); inputs: {context:
|
|
1097
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "20.3.9", type: XtRenderSubComponent, isStandalone: true, selector: "xt-render-sub", inputs: { context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: true, transformFunction: null }, componentType: { classPropertyName: "componentType", publicName: "componentType", isSignal: true, isRequired: false, transformFunction: null }, inputs: { classPropertyName: "inputs", publicName: "inputs", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { outputs: "outputs" }, viewQueries: [{ propertyName: "outlet", first: true, predicate: NgComponentOutlet, descendants: true, isSignal: true }], ngImport: i0, template: "{{componentType()}}\n<ng-container *ngComponentOutlet=\"type(); inputs: {context:realContext ()}\" />\n", styles: [""], dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"], exportAs: ["ngComponentOutlet"] }, { kind: "ngmodule", type: ReactiveFormsModule }] }); }
|
|
809
1098
|
}
|
|
810
1099
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: XtRenderSubComponent, decorators: [{
|
|
811
1100
|
type: Component,
|
|
812
1101
|
args: [{ selector: 'xt-render-sub', standalone: true, imports: [
|
|
813
1102
|
NgComponentOutlet,
|
|
814
1103
|
ReactiveFormsModule
|
|
815
|
-
], template: "{{componentType()}}\n<ng-container *ngComponentOutlet=\"type(); inputs: {context:
|
|
1104
|
+
], template: "{{componentType()}}\n<ng-container *ngComponentOutlet=\"type(); inputs: {context:realContext ()}\" />\n" }]
|
|
816
1105
|
}], propDecorators: { context: [{ type: i0.Input, args: [{ isSignal: true, alias: "context", required: true }] }], componentType: [{ type: i0.Input, args: [{ isSignal: true, alias: "componentType", required: false }] }], inputs: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputs", required: false }] }], outputs: [{ type: i0.Output, args: ["outputs"] }], outlet: [{ type: i0.ViewChild, args: [i0.forwardRef(() => NgComponentOutlet), { isSignal: true }] }] } });
|
|
817
1106
|
|
|
818
1107
|
class XtBaseInput {
|
|
@@ -987,20 +1276,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImpor
|
|
|
987
1276
|
}]
|
|
988
1277
|
}] });
|
|
989
1278
|
|
|
990
|
-
class StoreSupport {
|
|
991
|
-
static isStoreManagerAvailable() {
|
|
992
|
-
if (this.testStoreManager != null)
|
|
993
|
-
return true;
|
|
994
|
-
return (globalThis.xtStoreManager != undefined);
|
|
995
|
-
}
|
|
996
|
-
static getStoreManager() {
|
|
997
|
-
return this.testStoreManager ?? (globalThis.xtStoreManager());
|
|
998
|
-
}
|
|
999
|
-
static setTestStoreManager(testStoreManager) {
|
|
1000
|
-
StoreSupport.testStoreManager = testStoreManager;
|
|
1001
|
-
}
|
|
1002
|
-
}
|
|
1003
|
-
|
|
1004
1279
|
function attachToFormGroup(formGroup, controlName, value, valueType, resolver) {
|
|
1005
1280
|
// If it's a single value, just create the control
|
|
1006
1281
|
if (((value != null) && (isPrimitive(value))
|
|
@@ -1026,13 +1301,14 @@ function updateFormGroupWithValue(formGroup, value, valueType, resolver) {
|
|
|
1026
1301
|
}
|
|
1027
1302
|
for (const valueKey of keySet) {
|
|
1028
1303
|
const subValue = (value != null) ? value[valueKey] : null;
|
|
1029
|
-
const subType = resolver?.
|
|
1030
|
-
const
|
|
1304
|
+
const subType = resolver?.findType(valueType, valueKey, subValue) ?? undefined;
|
|
1305
|
+
const subTypeName = isTypeReference(subType) ? subType.toType : subType?.type;
|
|
1306
|
+
const primitive = (resolver != null) ? resolver?.isPrimitiveType(subType, subValue) : isPrimitive(subValue);
|
|
1031
1307
|
if (toDelete.delete(valueKey)) {
|
|
1032
1308
|
// Already a control
|
|
1033
1309
|
const oldControl = formGroup.get(valueKey);
|
|
1034
1310
|
// Is it the right type ?
|
|
1035
|
-
if (primitive) {
|
|
1311
|
+
if ((primitive) || (isTypeReference(subType))) {
|
|
1036
1312
|
// Must be an FormControl2
|
|
1037
1313
|
if (oldControl.controls === undefined) {
|
|
1038
1314
|
// It's ok, just set the value
|
|
@@ -1047,22 +1323,22 @@ function updateFormGroupWithValue(formGroup, value, valueType, resolver) {
|
|
|
1047
1323
|
if (oldControl.controls === undefined) {
|
|
1048
1324
|
const newFormGroup = new FormGroup({});
|
|
1049
1325
|
formGroup.setControl(valueKey, newFormGroup);
|
|
1050
|
-
updateFormGroupWithValue(newFormGroup, subValue,
|
|
1326
|
+
updateFormGroupWithValue(newFormGroup, subValue, subTypeName, resolver);
|
|
1051
1327
|
}
|
|
1052
1328
|
else {
|
|
1053
1329
|
// It was already a formgroup, so just update it
|
|
1054
|
-
updateFormGroupWithValue(oldControl, subValue,
|
|
1330
|
+
updateFormGroupWithValue(oldControl, subValue, subTypeName, resolver);
|
|
1055
1331
|
}
|
|
1056
1332
|
}
|
|
1057
1333
|
}
|
|
1058
1334
|
else {
|
|
1059
|
-
if (primitive) {
|
|
1335
|
+
if ((primitive) || (isTypeReference(subType))) {
|
|
1060
1336
|
formGroup.addControl(valueKey, new FormControl(subValue));
|
|
1061
1337
|
}
|
|
1062
1338
|
else {
|
|
1063
1339
|
const newFormGroup = new FormGroup({});
|
|
1064
1340
|
formGroup.addControl(valueKey, newFormGroup);
|
|
1065
|
-
updateFormGroupWithValue(newFormGroup, subValue,
|
|
1341
|
+
updateFormGroupWithValue(newFormGroup, subValue, subTypeName, resolver);
|
|
1066
1342
|
}
|
|
1067
1343
|
}
|
|
1068
1344
|
}
|
|
@@ -1111,6 +1387,7 @@ class HostTestFormComponent {
|
|
|
1111
1387
|
this.formDescription = input({}, ...(ngDevMode ? [{ debugName: "formDescription" }] : []));
|
|
1112
1388
|
// Or set the FormGroup directly
|
|
1113
1389
|
this.formGroup = input(...(ngDevMode ? [undefined, { debugName: "formGroup" }] : []));
|
|
1390
|
+
// parentFormGroup = this.builder.group<{[keys:string]: AbstractControl}>({});
|
|
1114
1391
|
this.createdFormGroup = null;
|
|
1115
1392
|
}
|
|
1116
1393
|
computedFormGroup() {
|
|
@@ -1118,6 +1395,7 @@ class HostTestFormComponent {
|
|
|
1118
1395
|
const formGroup = this.formGroup();
|
|
1119
1396
|
this.createdFormGroup = formGroup ?? generateFormGroup(this.formDescription());
|
|
1120
1397
|
}
|
|
1398
|
+
// this.parentFormGroup.addControl(this.controlName()??HostTestTypedFormComponent.CONTROL_NAME, this.createdFormGroup);
|
|
1121
1399
|
return this.createdFormGroup;
|
|
1122
1400
|
}
|
|
1123
1401
|
patchValue(newVal) {
|
|
@@ -1274,108 +1552,6 @@ function generateFormControl(formDescription) {
|
|
|
1274
1552
|
return new FormControl(formDescription);
|
|
1275
1553
|
}
|
|
1276
1554
|
|
|
1277
|
-
/**
|
|
1278
|
-
* A very light and not 100% compatible storemanager in case you are not using xt-store.
|
|
1279
|
-
* It can emulate XtStoreManager to some extends for doing some tests
|
|
1280
|
-
*/
|
|
1281
|
-
class StoreTestHelper {
|
|
1282
|
-
static ensureTestProviderOnly() {
|
|
1283
|
-
StoreSupport.setTestStoreManager(new TestStoreManager());
|
|
1284
|
-
}
|
|
1285
|
-
}
|
|
1286
|
-
class TestStoreManager {
|
|
1287
|
-
constructor() {
|
|
1288
|
-
this.defaultProvider = new TestStoreProvider();
|
|
1289
|
-
}
|
|
1290
|
-
getProvider(name) {
|
|
1291
|
-
return this.defaultProvider;
|
|
1292
|
-
}
|
|
1293
|
-
getProviderSafe(name) {
|
|
1294
|
-
return this.defaultProvider;
|
|
1295
|
-
}
|
|
1296
|
-
getDefaultProvider() {
|
|
1297
|
-
return this.defaultProvider;
|
|
1298
|
-
}
|
|
1299
|
-
getDefaultProviderSafe() {
|
|
1300
|
-
return this.defaultProvider;
|
|
1301
|
-
}
|
|
1302
|
-
}
|
|
1303
|
-
class TestStoreProvider {
|
|
1304
|
-
constructor() {
|
|
1305
|
-
this.data = new Map();
|
|
1306
|
-
}
|
|
1307
|
-
getOrCreateArray(name) {
|
|
1308
|
-
let ret = this.data.get(name);
|
|
1309
|
-
if (ret == null) {
|
|
1310
|
-
ret = new Map();
|
|
1311
|
-
this.data.set(name, ret);
|
|
1312
|
-
}
|
|
1313
|
-
return ret;
|
|
1314
|
-
}
|
|
1315
|
-
extractKey(value, create) {
|
|
1316
|
-
if (value._id != null)
|
|
1317
|
-
return value._id; // ManagedData key
|
|
1318
|
-
else if (value.id != null)
|
|
1319
|
-
return value.id;
|
|
1320
|
-
else {
|
|
1321
|
-
if (create === true) {
|
|
1322
|
-
const newId = new Date().getTime().toString();
|
|
1323
|
-
value._id = newId;
|
|
1324
|
-
return newId;
|
|
1325
|
-
}
|
|
1326
|
-
return value.toString();
|
|
1327
|
-
}
|
|
1328
|
-
}
|
|
1329
|
-
storeEntity(name, entity) {
|
|
1330
|
-
this.getOrCreateArray(name).set(this.extractKey(entity, true), entity);
|
|
1331
|
-
return Promise.resolve(entity);
|
|
1332
|
-
}
|
|
1333
|
-
safeLoadEntity(name, key) {
|
|
1334
|
-
const ret = this.getOrCreateArray(name).get(key);
|
|
1335
|
-
if (ret == null) {
|
|
1336
|
-
throw new Error("No entity named " + name + " with key " + key);
|
|
1337
|
-
}
|
|
1338
|
-
return Promise.resolve(ret);
|
|
1339
|
-
}
|
|
1340
|
-
loadEntity(name, key) {
|
|
1341
|
-
return Promise.resolve(this.getOrCreateArray(name).get(key));
|
|
1342
|
-
}
|
|
1343
|
-
deleteEntity(name, key) {
|
|
1344
|
-
return Promise.resolve(this.getOrCreateArray(name).delete(key));
|
|
1345
|
-
}
|
|
1346
|
-
searchEntities(name, ...criteria) {
|
|
1347
|
-
if ((criteria != null) && (criteria.length > 0)) {
|
|
1348
|
-
throw new Error('Method not implemented.');
|
|
1349
|
-
}
|
|
1350
|
-
// No criteria defined, just send the full list
|
|
1351
|
-
const ret = new Array();
|
|
1352
|
-
for (const toAdd of this.getOrCreateArray(name).values()) {
|
|
1353
|
-
ret.push(toAdd);
|
|
1354
|
-
}
|
|
1355
|
-
return from([ret]);
|
|
1356
|
-
}
|
|
1357
|
-
searchAndPrepareEntities(name, sort, groupBy, transformer, ...criteria) {
|
|
1358
|
-
throw new Error('Method not implemented.');
|
|
1359
|
-
}
|
|
1360
|
-
canStoreDocument() {
|
|
1361
|
-
return true;
|
|
1362
|
-
}
|
|
1363
|
-
storeDocument(toStore) {
|
|
1364
|
-
const ret = new TestDocumentInfo(toStore.name, true, URL.createObjectURL(toStore));
|
|
1365
|
-
return Promise.resolve(ret);
|
|
1366
|
-
}
|
|
1367
|
-
storeDocuments(toStore) {
|
|
1368
|
-
throw new Error('Method not implemented.');
|
|
1369
|
-
}
|
|
1370
|
-
}
|
|
1371
|
-
class TestDocumentInfo {
|
|
1372
|
-
constructor(documentName, isUrl, documentId) {
|
|
1373
|
-
this.documentId = documentId;
|
|
1374
|
-
this.documentName = documentName;
|
|
1375
|
-
this.isUrl = isUrl;
|
|
1376
|
-
}
|
|
1377
|
-
}
|
|
1378
|
-
|
|
1379
1555
|
/*
|
|
1380
1556
|
* Public API Surface of xt-components
|
|
1381
1557
|
*/
|
|
@@ -1384,5 +1560,5 @@ class TestDocumentInfo {
|
|
|
1384
1560
|
* Generated bundle index. Do not edit.
|
|
1385
1561
|
*/
|
|
1386
1562
|
|
|
1387
|
-
export { HostTestFormComponent, HostTestSimpleComponent, HostTestTypedComponent, HostTestTypedFormComponent, StoreSupport, StoreTestHelper, TestDocumentInfo, TestStoreManager, TestStoreProvider, XT_REGISTRY_TOKEN, XT_RESOLVER_TOKEN, XT_TYPE_RESOLVER_TOKEN, XtBaseContext, XtCompositeComponent, XtMessageHandler, XtPluginRegistry, XtRenderComponent, XtRenderSubComponent, XtResolvedComponent, XtResolverService, XtSimpleComponent, XtUnitTestHelper, attachToFormGroup, initXtPluginRegistry, updateFormGroupWithValue, xtPluginRegistry };
|
|
1563
|
+
export { HostTestFormComponent, HostTestSimpleComponent, HostTestTypedComponent, HostTestTypedFormComponent, StoreSupport, StoreTestHelper, TestDocumentInfo, TestStoreCriteria, TestStoreManager, TestStoreProvider, XT_REGISTRY_TOKEN, XT_RESOLVER_TOKEN, XT_TYPE_RESOLVER_TOKEN, XtBaseContext, XtCompositeComponent, XtMessageHandler, XtPluginRegistry, XtRenderComponent, XtRenderSubComponent, XtResolvedComponent, XtResolverService, XtSimpleComponent, XtUnitTestHelper, attachToFormGroup, initXtPluginRegistry, updateFormGroupWithValue, xtPluginRegistry };
|
|
1388
1564
|
//# sourceMappingURL=xt-components.mjs.map
|