@jsonforms/core 3.0.0-beta.1 → 3.0.0-beta.4

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.
Files changed (115) hide show
  1. package/README.md +11 -0
  2. package/docs/assets/js/search.json +1 -1
  3. package/docs/enums/ruleeffect.html +4 -4
  4. package/docs/globals.html +357 -217
  5. package/docs/index.html +29 -4
  6. package/docs/interfaces/addcellrendereraction.html +3 -3
  7. package/docs/interfaces/addrendereraction.html +3 -3
  8. package/docs/interfaces/adduischemaaction.html +3 -3
  9. package/docs/interfaces/andcondition.html +2 -2
  10. package/docs/interfaces/arraycontrolprops.html +21 -21
  11. package/docs/interfaces/arraylayoutprops.html +21 -21
  12. package/docs/interfaces/categorization.html +5 -5
  13. package/docs/interfaces/category.html +5 -5
  14. package/docs/interfaces/cellprops.html +12 -12
  15. package/docs/interfaces/combinatorrendererprops.html +143 -36
  16. package/docs/interfaces/composablecondition.html +2 -2
  17. package/docs/interfaces/condition.html +1 -1
  18. package/docs/interfaces/controlelement.html +22 -4
  19. package/docs/interfaces/controlprops.html +16 -16
  20. package/docs/interfaces/controlstate.html +2 -2
  21. package/docs/interfaces/controlwithdetailprops.html +17 -17
  22. package/docs/interfaces/dispatchcellprops.html +10 -10
  23. package/docs/interfaces/dispatchcellstateprops.html +10 -10
  24. package/docs/interfaces/dispatchpropsofarraycontrol.html +4 -4
  25. package/docs/interfaces/dispatchpropsofcontrol.html +1 -1
  26. package/docs/interfaces/dispatchpropsofmultienumcontrol.html +2 -2
  27. package/docs/interfaces/enumcellprops.html +13 -13
  28. package/docs/interfaces/enumoption.html +2 -2
  29. package/docs/interfaces/grouplayout.html +5 -5
  30. package/docs/interfaces/horizontallayout.html +4 -4
  31. package/docs/interfaces/initactionoptions.html +14 -0
  32. package/docs/interfaces/internationalizable.html +167 -0
  33. package/docs/interfaces/jsonformscore.html +17 -3
  34. package/docs/interfaces/jsonformsprops.html +9 -9
  35. package/docs/interfaces/labeldescription.html +2 -2
  36. package/docs/interfaces/labelelement.html +4 -4
  37. package/docs/interfaces/layout.html +4 -4
  38. package/docs/interfaces/layoutprops.html +10 -10
  39. package/docs/interfaces/leafcondition.html +2 -2
  40. package/docs/interfaces/orcondition.html +2 -2
  41. package/docs/interfaces/ownpropsofcell.html +9 -9
  42. package/docs/interfaces/ownpropsofcontrol.html +9 -12
  43. package/docs/interfaces/ownpropsofenum.html +1 -1
  44. package/docs/interfaces/ownpropsofenumcell.html +10 -10
  45. package/docs/interfaces/ownpropsofjsonformsrenderer.html +8 -8
  46. package/docs/interfaces/ownpropsoflayout.html +9 -9
  47. package/docs/interfaces/ownpropsofmasterlistitem.html +6 -6
  48. package/docs/interfaces/ownpropsofrenderer.html +8 -8
  49. package/docs/interfaces/registerdefaultdataaction.html +3 -3
  50. package/docs/interfaces/removecellrendereraction.html +3 -3
  51. package/docs/interfaces/removerendereraction.html +3 -3
  52. package/docs/interfaces/removeuischemaaction.html +2 -2
  53. package/docs/interfaces/rendererprops.html +9 -9
  54. package/docs/interfaces/rule.html +2 -2
  55. package/docs/interfaces/schemabasedcondition.html +2 -2
  56. package/docs/interfaces/setajvaction.html +2 -2
  57. package/docs/interfaces/setconfigaction.html +2 -2
  58. package/docs/interfaces/setlocaleaction.html +2 -2
  59. package/docs/interfaces/setschemaaction.html +2 -2
  60. package/docs/interfaces/settranslatoraction.html +3 -3
  61. package/docs/interfaces/setuischemaaction.html +2 -2
  62. package/docs/interfaces/setvalidationmodeaction.html +2 -2
  63. package/docs/interfaces/statepropsofarraycontrol.html +17 -17
  64. package/docs/interfaces/statepropsofarraylayout.html +17 -17
  65. package/docs/interfaces/statepropsofcell.html +11 -11
  66. package/docs/interfaces/statepropsofcombinator.html +147 -40
  67. package/docs/interfaces/statepropsofcontrol.html +18 -15
  68. package/docs/interfaces/statepropsofcontrolwithdetail.html +16 -16
  69. package/docs/interfaces/statepropsofenumcell.html +12 -12
  70. package/docs/interfaces/statepropsofjsonformsrenderer.html +9 -9
  71. package/docs/interfaces/statepropsoflayout.html +10 -10
  72. package/docs/interfaces/statepropsofmasteritem.html +7 -7
  73. package/docs/interfaces/statepropsofrenderer.html +9 -9
  74. package/docs/interfaces/statepropsofscopedrenderer.html +12 -12
  75. package/docs/interfaces/uischemaelement.html +3 -3
  76. package/docs/interfaces/unregisterdefaultdataaction.html +2 -2
  77. package/docs/interfaces/updatei18naction.html +4 -4
  78. package/docs/interfaces/verticallayout.html +4 -4
  79. package/docs/interfaces/withclassname.html +1 -1
  80. package/lib/actions/actions.d.ts +1 -0
  81. package/lib/jsonforms-core.cjs.js +201 -179
  82. package/lib/jsonforms-core.cjs.js.map +1 -1
  83. package/lib/jsonforms-core.esm.js +182 -166
  84. package/lib/jsonforms-core.esm.js.map +1 -1
  85. package/lib/models/uischema.d.ts +10 -1
  86. package/lib/reducers/core.d.ts +1 -0
  87. package/lib/reducers/reducers.d.ts +2 -2
  88. package/lib/testers/testers.d.ts +8 -7
  89. package/lib/util/combinators.d.ts +0 -1
  90. package/lib/util/path.d.ts +10 -0
  91. package/lib/util/renderer.d.ts +2 -2
  92. package/lib/util/resolvers.d.ts +1 -1
  93. package/lib/util/util.d.ts +1 -1
  94. package/package.json +2 -2
  95. package/src/actions/actions.ts +1 -0
  96. package/src/generators/uischema.ts +4 -4
  97. package/src/i18n/i18nUtil.ts +10 -7
  98. package/src/models/uischema.ts +14 -1
  99. package/src/reducers/core.ts +30 -3
  100. package/src/reducers/reducers.ts +12 -4
  101. package/src/testers/testers.ts +61 -34
  102. package/src/util/combinators.ts +17 -32
  103. package/src/util/label.ts +2 -2
  104. package/src/util/path.ts +18 -6
  105. package/src/util/renderer.ts +20 -32
  106. package/src/util/resolvers.ts +57 -68
  107. package/src/util/util.ts +1 -1
  108. package/stats.html +1 -1
  109. package/test/generators/uischema.test.ts +18 -0
  110. package/test/i18n/i18nUtil.test.ts +41 -1
  111. package/test/reducers/core.test.ts +203 -1
  112. package/test/testers.test.ts +208 -120
  113. package/test/util/path.test.ts +37 -20
  114. package/test/util/renderer.test.ts +1 -1
  115. package/test/util/resolvers.test.ts +99 -8
@@ -9,6 +9,14 @@ export interface Scopable {
9
9
  */
10
10
  scope: string;
11
11
  }
12
+ /**
13
+ * Interface for describing an UI schema element that can provide an internationalization base key.
14
+ * If defined, this key is suffixed to derive applicable message keys for the UI schema element.
15
+ * For example, such suffixes are `.label` or `.description` to derive the corresponding message keys for a control element.
16
+ */
17
+ export interface Internationalizable {
18
+ i18n?: string;
19
+ }
12
20
  /**
13
21
  * A rule that may be attached to any UI schema element.
14
22
  */
@@ -163,7 +171,7 @@ export interface LabelElement extends UISchemaElement {
163
171
  * A control element. The scope property of the control determines
164
172
  * to which part of the schema the control should be bound.
165
173
  */
166
- export interface ControlElement extends UISchemaElement, Scopable {
174
+ export interface ControlElement extends UISchemaElement, Scopable, Internationalizable {
167
175
  type: 'Control';
168
176
  /**
169
177
  * An optional label that will be associated with the control
@@ -197,5 +205,6 @@ export interface Categorization extends UISchemaElement {
197
205
  */
198
206
  elements: (Category | Categorization)[];
199
207
  }
208
+ export declare const isInternationalized: (element: unknown) => element is Required<Internationalizable>;
200
209
  export declare const isGroup: (layout: Layout) => layout is GroupLayout;
201
210
  export declare const isLayout: (uischema: UISchemaElement) => uischema is Layout;
@@ -9,6 +9,7 @@ export interface JsonFormsCore {
9
9
  schema: JsonSchema;
10
10
  uischema: UISchemaElement;
11
11
  errors?: ErrorObject[];
12
+ additionalErrors?: ErrorObject[];
12
13
  validator?: ValidateFunction;
13
14
  ajv?: Ajv;
14
15
  validationMode?: ValidationMode;
@@ -17,10 +17,10 @@ export declare const jsonFormsReducerConfig: {
17
17
  * @param schema the JSON schema describing the data to be rendered
18
18
  * @param schemaPath the according schema path
19
19
  * @param path the instance path
20
- * @param fallbackLayoutType the type of the layout to use
20
+ * @param fallback the type of the layout to use or a UI-schema-generator function
21
21
  * @param control may be checked for embedded inline uischema options
22
22
  */
23
- export declare const findUISchema: (uischemas: JsonFormsUISchemaRegistryEntry[], schema: JsonSchema, schemaPath: string, path: string, fallbackLayoutType?: string, control?: ControlElement, rootSchema?: JsonSchema) => UISchemaElement;
23
+ export declare const findUISchema: (uischemas: JsonFormsUISchemaRegistryEntry[], schema: JsonSchema, schemaPath: string, path: string, fallback?: string | (() => UISchemaElement), control?: ControlElement, rootSchema?: JsonSchema) => UISchemaElement;
24
24
  export declare const getErrorAt: (instancePath: string, schema: JsonSchema) => (state: JsonFormsState) => import("ajv").ErrorObject<string, Record<string, any>, unknown>[];
25
25
  export declare const getSubErrorsAt: (instancePath: string, schema: JsonSchema) => (state: JsonFormsState) => import("ajv").ErrorObject<string, Record<string, any>, unknown>[];
26
26
  export declare const getConfig: (state: JsonFormsState) => any;
@@ -7,12 +7,13 @@ import { Categorization, ControlElement, JsonSchema, UISchemaElement } from '../
7
7
  export declare const NOT_APPLICABLE = -1;
8
8
  /**
9
9
  * A tester is a function that receives an UI schema and a JSON schema and returns a boolean.
10
+ * The rootSchema is handed over as context. Can be used to resolve references.
10
11
  */
11
- export declare type Tester = (uischema: UISchemaElement, schema: JsonSchema) => boolean;
12
+ export declare type Tester = (uischema: UISchemaElement, schema: JsonSchema, rootSchema: JsonSchema) => boolean;
12
13
  /**
13
14
  * A ranked tester associates a tester with a number.
14
15
  */
15
- export declare type RankedTester = (uischema: UISchemaElement, schema: JsonSchema) => number;
16
+ export declare type RankedTester = (uischema: UISchemaElement, schema: JsonSchema, rootSchema: JsonSchema) => number;
16
17
  export declare const isControl: (uischema: any) => uischema is ControlElement;
17
18
  /**
18
19
  * Only applicable for Controls.
@@ -24,8 +25,8 @@ export declare const isControl: (uischema: any) => uischema is ControlElement;
24
25
  * @param {(JsonSchema) => boolean} predicate the predicate that should be
25
26
  * applied to the resolved sub-schema
26
27
  */
27
- export declare const schemaMatches: (predicate: (schema: JsonSchema) => boolean) => Tester;
28
- export declare const schemaSubPathMatches: (subPath: string, predicate: (schema: JsonSchema) => boolean) => Tester;
28
+ export declare const schemaMatches: (predicate: (schema: JsonSchema, rootSchema: JsonSchema) => boolean) => Tester;
29
+ export declare const schemaSubPathMatches: (subPath: string, predicate: (schema: JsonSchema, rootSchema: JsonSchema) => boolean) => Tester;
29
30
  /**
30
31
  * Only applicable for Controls.
31
32
  *
@@ -96,8 +97,8 @@ export declare const or: (...testers: Tester[]) => Tester;
96
97
  * @param {number} rank the rank to be returned in case the tester returns true
97
98
  * @param {Tester} tester a tester
98
99
  */
99
- export declare const rankWith: (rank: number, tester: Tester) => (uischema: UISchemaElement, schema: JsonSchema) => number;
100
- export declare const withIncreasedRank: (by: number, rankedTester: RankedTester) => (uischema: UISchemaElement, schema: JsonSchema) => number;
100
+ export declare const rankWith: (rank: number, tester: Tester) => (uischema: UISchemaElement, schema: JsonSchema, rootSchema: JsonSchema) => number;
101
+ export declare const withIncreasedRank: (by: number, rankedTester: RankedTester) => (uischema: UISchemaElement, schema: JsonSchema, rootSchema: JsonSchema) => number;
101
102
  /**
102
103
  * Default tester for boolean.
103
104
  * @type {RankedTester}
@@ -172,7 +173,7 @@ export declare const isObjectArray: Tester;
172
173
  * @type {Tester}
173
174
  */
174
175
  export declare const isObjectArrayControl: Tester;
175
- export declare const isObjectArrayWithNesting: (uischema: UISchemaElement, schema: JsonSchema) => boolean;
176
+ export declare const isObjectArrayWithNesting: (uischema: UISchemaElement, schema: JsonSchema, rootSchema: JsonSchema) => boolean;
176
177
  /**
177
178
  * Synonym for isObjectArrayControl
178
179
  */
@@ -6,5 +6,4 @@ export interface CombinatorSubSchemaRenderInfo {
6
6
  label: string;
7
7
  }
8
8
  export declare type CombinatorKeyword = 'anyOf' | 'oneOf' | 'allOf';
9
- export declare const resolveSubSchemas: (schema: JsonSchema, rootSchema: JsonSchema, keyword: CombinatorKeyword) => JsonSchema;
10
9
  export declare const createCombinatorRenderInfos: (combinatorSubSchemas: JsonSchema[], rootSchema: JsonSchema, keyword: CombinatorKeyword, control: ControlElement, path: string, uischemas: JsonFormsUISchemaRegistryEntry[]) => CombinatorSubSchemaRenderInfo[];
@@ -23,3 +23,13 @@ export declare const toDataPathSegments: (schemaPath: string) => string[];
23
23
  */
24
24
  export declare const toDataPath: (schemaPath: string) => string;
25
25
  export declare const composeWithUi: (scopableUi: Scopable, path: string) => string;
26
+ /**
27
+ * Encodes the given segment to be used as part of a JSON Pointer
28
+ *
29
+ * JSON Pointer has special meaning for "/" and "~", therefore these must be encoded
30
+ */
31
+ export declare const encode: (segment: string) => string;
32
+ /**
33
+ * Decodes a given JSON Pointer segment to its "normal" representation
34
+ */
35
+ export declare const decode: (pointerSegment: string) => string;
@@ -1,5 +1,5 @@
1
1
  import { ControlElement, JsonSchema, UISchemaElement } from '../models';
2
- import type { JsonFormsCellRendererRegistryEntry, JsonFormsRendererRegistryEntry } from '../reducers';
2
+ import { JsonFormsCellRendererRegistryEntry, JsonFormsRendererRegistryEntry } from '../reducers';
3
3
  import { JsonFormsUISchemaRegistryEntry } from '../reducers';
4
4
  import { RankedTester } from '../testers';
5
5
  import { CombinatorKeyword } from './combinators';
@@ -359,7 +359,7 @@ export declare const controlDefaultProps: {
359
359
  path: string;
360
360
  direction: 'row' | 'column';
361
361
  };
362
- export interface StatePropsOfCombinator extends OwnPropsOfControl {
362
+ export interface StatePropsOfCombinator extends StatePropsOfControl {
363
363
  rootSchema: JsonSchema;
364
364
  path: string;
365
365
  id: string;
@@ -22,4 +22,4 @@ export declare const findAllRefs: (schema: JsonSchema, result?: ReferenceSchemaM
22
22
  * @param {JsonSchema} rootSchema the actual root schema
23
23
  * @returns {JsonSchema} the resolved sub-schema
24
24
  */
25
- export declare const resolveSchema: (schema: JsonSchema, schemaPath: string, rootSchema?: JsonSchema) => JsonSchema;
25
+ export declare const resolveSchema: (schema: JsonSchema, schemaPath: string, rootSchema: JsonSchema) => JsonSchema;
@@ -18,7 +18,7 @@ export declare const deriveTypes: (jsonSchema: JsonSchema) => string[];
18
18
  * Convenience wrapper around resolveData and resolveSchema.
19
19
  */
20
20
  export declare const Resolve: {
21
- schema(schema: JsonSchema, schemaPath: string, rootSchema?: JsonSchema): JsonSchema;
21
+ schema(schema: JsonSchema, schemaPath: string, rootSchema: JsonSchema): JsonSchema;
22
22
  data(data: any, path: string): any;
23
23
  };
24
24
  export declare const Paths: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsonforms/core",
3
- "version": "3.0.0-beta.1",
3
+ "version": "3.0.0-beta.4",
4
4
  "description": "Core module of JSON Forms",
5
5
  "repository": "https://github.com/eclipsesource/jsonforms",
6
6
  "bugs": "https://github.com/eclipsesource/jsonforms/issues",
@@ -88,5 +88,5 @@
88
88
  "typedoc": "^0.19.2",
89
89
  "typescript": "4.2.3"
90
90
  },
91
- "gitHead": "8c3b6263f360ca192c0a20a343a19c5ffb3a10f7"
91
+ "gitHead": "413b9767ea8e2c0b6adb3919f5e6b76263d4be31"
92
92
  }
@@ -100,6 +100,7 @@ export interface UpdateCoreAction {
100
100
  export interface InitActionOptions {
101
101
  ajv?: AJV;
102
102
  validationMode?: ValidationMode;
103
+ additionalErrors?: ErrorObject[];
103
104
  }
104
105
 
105
106
  export interface SetValidationModeAction {
@@ -35,7 +35,7 @@ import {
35
35
  Layout,
36
36
  UISchemaElement
37
37
  } from '../models';
38
- import { deriveTypes, resolveSchema } from '../util';
38
+ import { deriveTypes, encode, resolveSchema } from '../util';
39
39
 
40
40
  /**
41
41
  * Creates a new ILayout.
@@ -122,7 +122,7 @@ const generateUISchema = (
122
122
  ): UISchemaElement => {
123
123
  if (!isEmpty(jsonSchema) && jsonSchema.$ref !== undefined) {
124
124
  return generateUISchema(
125
- resolveSchema(rootSchema, jsonSchema.$ref),
125
+ resolveSchema(rootSchema, jsonSchema.$ref, rootSchema),
126
126
  schemaElements,
127
127
  currentRef,
128
128
  schemaName,
@@ -162,9 +162,9 @@ const generateUISchema = (
162
162
  const nextRef: string = currentRef + '/properties';
163
163
  Object.keys(jsonSchema.properties).map(propName => {
164
164
  let value = jsonSchema.properties[propName];
165
- const ref = `${nextRef}/${propName}`;
165
+ const ref = `${nextRef}/${encode(propName)}`;
166
166
  if (value.$ref !== undefined) {
167
- value = resolveSchema(rootSchema, value.$ref);
167
+ value = resolveSchema(rootSchema, value.$ref, rootSchema);
168
168
  }
169
169
  generateUISchema(
170
170
  value,
@@ -1,5 +1,5 @@
1
1
  import { ErrorObject } from 'ajv';
2
- import { UISchemaElement } from '../models';
2
+ import { isInternationalized, UISchemaElement } from '../models';
3
3
  import { getControlPath } from '../reducers';
4
4
  import { formatErrorMessage } from '../util';
5
5
  import { i18nJsonSchema, ErrorTranslator, Translator } from './i18nTypes';
@@ -8,7 +8,10 @@ export const getI18nKeyPrefixBySchema = (
8
8
  schema: i18nJsonSchema | undefined,
9
9
  uischema: UISchemaElement | undefined
10
10
  ): string | undefined => {
11
- return uischema?.options?.i18n ?? schema?.i18n ?? undefined;
11
+ if (isInternationalized(uischema)) {
12
+ return uischema.i18n;
13
+ }
14
+ return schema?.i18n ?? undefined;
12
15
  };
13
16
 
14
17
  /**
@@ -54,26 +57,26 @@ export const defaultErrorTranslator: ErrorTranslator = (error, t, uischema) => {
54
57
  getControlPath(error),
55
58
  `error.${error.keyword}`
56
59
  );
57
- const specializedKeywordMessage = t(i18nKey, undefined);
60
+ const specializedKeywordMessage = t(i18nKey, undefined, { error } );
58
61
  if (specializedKeywordMessage !== undefined) {
59
62
  return specializedKeywordMessage;
60
63
  }
61
64
 
62
65
  // check whether there is a generic keyword message
63
- const genericKeywordMessage = t(`error.${error.keyword}`, undefined);
66
+ const genericKeywordMessage = t(`error.${error.keyword}`, undefined, { error });
64
67
  if (genericKeywordMessage !== undefined) {
65
68
  return genericKeywordMessage;
66
69
  }
67
70
 
68
71
  // check whether there is a customization for the default message
69
- const messageCustomization = t(error.message, undefined);
72
+ const messageCustomization = t(error.message, undefined, { error });
70
73
  if (messageCustomization !== undefined) {
71
74
  return messageCustomization;
72
75
  }
73
76
 
74
77
  // rewrite required property messages (if they were not customized) as we place them next to the respective input
75
78
  if (error.keyword === 'required' && error.message?.startsWith('must have required property')) {
76
- return t('is a required property', 'is a required property');
79
+ return t('is a required property', 'is a required property', { error });
77
80
  }
78
81
 
79
82
  return error.message;
@@ -94,7 +97,7 @@ export const getCombinedErrorMessage = (
94
97
  if (errors.length > 0 && t) {
95
98
  // check whether there is a special message which overwrites all others
96
99
  const customErrorKey = getI18nKey(schema, uischema, path, 'error.custom');
97
- const specializedErrorMessage = t(customErrorKey, undefined);
100
+ const specializedErrorMessage = t(customErrorKey, undefined, {schema, uischema, path, errors});
98
101
  if (specializedErrorMessage !== undefined) {
99
102
  return specializedErrorMessage;
100
103
  }
@@ -36,6 +36,15 @@ export interface Scopable {
36
36
  scope: string;
37
37
  }
38
38
 
39
+ /**
40
+ * Interface for describing an UI schema element that can provide an internationalization base key.
41
+ * If defined, this key is suffixed to derive applicable message keys for the UI schema element.
42
+ * For example, such suffixes are `.label` or `.description` to derive the corresponding message keys for a control element.
43
+ */
44
+ export interface Internationalizable {
45
+ i18n?: string;
46
+ }
47
+
39
48
  /**
40
49
  * A rule that may be attached to any UI schema element.
41
50
  */
@@ -207,7 +216,7 @@ export interface LabelElement extends UISchemaElement {
207
216
  * A control element. The scope property of the control determines
208
217
  * to which part of the schema the control should be bound.
209
218
  */
210
- export interface ControlElement extends UISchemaElement, Scopable {
219
+ export interface ControlElement extends UISchemaElement, Scopable, Internationalizable {
211
220
  type: 'Control';
212
221
  /**
213
222
  * An optional label that will be associated with the control
@@ -244,6 +253,10 @@ export interface Categorization extends UISchemaElement {
244
253
  elements: (Category | Categorization)[];
245
254
  }
246
255
 
256
+ export const isInternationalized = (element: unknown): element is Required<Internationalizable> => {
257
+ return typeof element === 'object' && element !== null && typeof (element as Internationalizable).i18n === 'string';
258
+ }
259
+
247
260
  export const isGroup = (layout: Layout): layout is GroupLayout =>
248
261
  layout.type === 'Group';
249
262
 
@@ -65,6 +65,7 @@ export interface JsonFormsCore {
65
65
  schema: JsonSchema;
66
66
  uischema: UISchemaElement;
67
67
  errors?: ErrorObject[];
68
+ additionalErrors?: ErrorObject[];
68
69
  validator?: ValidateFunction;
69
70
  ajv?: Ajv;
70
71
  validationMode?: ValidationMode;
@@ -78,6 +79,7 @@ const initState: JsonFormsCore = {
78
79
  validator: undefined,
79
80
  ajv: undefined,
80
81
  validationMode: 'ValidateAndShow',
82
+ additionalErrors: []
81
83
  };
82
84
 
83
85
  const reuseAjvForSchema = (ajv: Ajv, schema: JsonSchema): Ajv => {
@@ -133,6 +135,23 @@ const hasValidationModeOption = (option: any): option is InitActionOptions => {
133
135
  return false;
134
136
  };
135
137
 
138
+ const hasAdditionalErrorsOption = (option: any): option is InitActionOptions => {
139
+ if (option) {
140
+ return option.additionalErrors !== undefined;
141
+ }
142
+ return false;
143
+ };
144
+
145
+ const getAdditionalErrors = (
146
+ state: JsonFormsCore,
147
+ action?: InitAction | UpdateCoreAction
148
+ ): ErrorObject[] => {
149
+ if (action && hasAdditionalErrorsOption(action.options)) {
150
+ return action.options.additionalErrors;
151
+ }
152
+ return state.additionalErrors;
153
+ };
154
+
136
155
  // tslint:disable-next-line: cyclomatic-complexity
137
156
  export const coreReducer: Reducer<JsonFormsCore, CoreActions> = (
138
157
  state = initState,
@@ -145,12 +164,14 @@ export const coreReducer: Reducer<JsonFormsCore, CoreActions> = (
145
164
  const validationMode = getValidationMode(state, action);
146
165
  const v = validationMode === 'NoValidation' ? undefined : thisAjv.compile(action.schema);
147
166
  const e = validate(v, action.data);
167
+ const additionalErrors = getAdditionalErrors(state, action);
148
168
 
149
169
  return {
150
170
  ...state,
151
171
  data: action.data,
152
172
  schema: action.schema,
153
173
  uischema: action.uischema,
174
+ additionalErrors,
154
175
  errors: e,
155
176
  validator: v,
156
177
  ajv: thisAjv,
@@ -176,6 +197,7 @@ export const coreReducer: Reducer<JsonFormsCore, CoreActions> = (
176
197
  } else if (state.data !== action.data) {
177
198
  errors = validate(validator, action.data);
178
199
  }
200
+ const additionalErrors = getAdditionalErrors(state, action);
179
201
 
180
202
  const stateChanged =
181
203
  state.data !== action.data ||
@@ -184,7 +206,8 @@ export const coreReducer: Reducer<JsonFormsCore, CoreActions> = (
184
206
  state.ajv !== thisAjv ||
185
207
  state.errors !== errors ||
186
208
  state.validator !== validator ||
187
- state.validationMode !== validationMode
209
+ state.validationMode !== validationMode ||
210
+ state.additionalErrors !== additionalErrors
188
211
  return stateChanged
189
212
  ? {
190
213
  ...state,
@@ -195,6 +218,7 @@ export const coreReducer: Reducer<JsonFormsCore, CoreActions> = (
195
218
  errors: isEqual(errors, state.errors) ? state.errors : errors,
196
219
  validator: validator,
197
220
  validationMode: validationMode,
221
+ additionalErrors
198
222
  }
199
223
  : state;
200
224
  }
@@ -391,8 +415,11 @@ const getErrorsAt = (
391
415
  instancePath: string,
392
416
  schema: JsonSchema,
393
417
  matchPath: (path: string) => boolean
394
- ) => (state: JsonFormsCore): ErrorObject[] =>
395
- errorsAt(instancePath, schema, matchPath)(state.validationMode === 'ValidateAndHide' ? [] : state.errors);
418
+ ) => (state: JsonFormsCore): ErrorObject[] => {
419
+ const errors = state.errors ?? [];
420
+ const additionalErrors = state.additionalErrors ?? [];
421
+ return errorsAt(instancePath, schema, matchPath)(state.validationMode === 'ValidateAndHide' ? additionalErrors : [...errors, ...additionalErrors]);
422
+ }
396
423
 
397
424
  export const errorAt = (instancePath: string, schema: JsonSchema) =>
398
425
  getErrorsAt(instancePath, schema, path => path === instancePath);
@@ -67,7 +67,7 @@ export const jsonFormsReducerConfig = {
67
67
  * @param schema the JSON schema describing the data to be rendered
68
68
  * @param schemaPath the according schema path
69
69
  * @param path the instance path
70
- * @param fallbackLayoutType the type of the layout to use
70
+ * @param fallback the type of the layout to use or a UI-schema-generator function
71
71
  * @param control may be checked for embedded inline uischema options
72
72
  */
73
73
  export const findUISchema = (
@@ -75,7 +75,7 @@ export const findUISchema = (
75
75
  schema: JsonSchema,
76
76
  schemaPath: string,
77
77
  path: string,
78
- fallbackLayoutType = 'VerticalLayout',
78
+ fallback: string | (() => UISchemaElement) = 'VerticalLayout',
79
79
  control?: ControlElement,
80
80
  rootSchema?: JsonSchema
81
81
  ): UISchemaElement => {
@@ -83,8 +83,12 @@ export const findUISchema = (
83
83
  if (control && control.options && control.options.detail) {
84
84
  if (typeof control.options.detail === 'string') {
85
85
  if (control.options.detail.toUpperCase() === 'GENERATE') {
86
+ //use fallback generation function
87
+ if(typeof fallback === "function"){
88
+ return fallback();
89
+ }
86
90
  // force generation of uischema
87
- return Generate.uiSchema(schema, fallbackLayoutType);
91
+ return Generate.uiSchema(schema, fallback);
88
92
  }
89
93
  } else if (typeof control.options.detail === 'object') {
90
94
  // check if detail is a valid uischema
@@ -99,7 +103,11 @@ export const findUISchema = (
99
103
  // default
100
104
  const uiSchema = findMatchingUISchema(uischemas)(schema, schemaPath, path);
101
105
  if (uiSchema === undefined) {
102
- return Generate.uiSchema(schema, fallbackLayoutType, '#', rootSchema);
106
+ //use fallback generation function
107
+ if(typeof fallback === 'function'){
108
+ return fallback();
109
+ }
110
+ return Generate.uiSchema(schema, fallback, '#', rootSchema);
103
111
  }
104
112
  return uiSchema;
105
113
  };