@syncfusion/ej2-form-renderer 34.2.8 → 35.1.42
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/dist/ej2-form-renderer.umd.min.js +2 -2
- package/dist/ej2-form-renderer.umd.min.js.map +1 -1
- package/dist/es6/ej2-form-renderer.es2015.js +3271 -1523
- package/dist/es6/ej2-form-renderer.es2015.js.map +1 -1
- package/dist/es6/ej2-form-renderer.es5.js +3326 -1540
- package/dist/es6/ej2-form-renderer.es5.js.map +1 -1
- package/dist/global/ej2-form-renderer.min.js +2 -2
- package/dist/global/ej2-form-renderer.min.js.map +1 -1
- package/dist/global/index.d.ts +1 -1
- package/package.json +11 -11
- package/src/{common → form-renderer/common}/checkbox-group.js +1 -1
- package/src/{common → form-renderer/common}/conditional-rule-engine.d.ts +1 -6
- package/src/{common → form-renderer/common}/custom-validation-engine.d.ts +1 -1
- package/src/{common → form-renderer/common}/expressions/expression-engine.d.ts +1 -4
- package/src/{common → form-renderer/common}/expressions/expression-parser.d.ts +1 -9
- package/src/{common → form-renderer/common}/index.d.ts +2 -0
- package/src/{common → form-renderer/common}/index.js +2 -0
- package/src/{common → form-renderer/common}/json-converter.d.ts +6 -1
- package/src/{common → form-renderer/common}/json-converter.js +49 -8
- package/src/form-renderer/common/props-forwarder.d.ts +38 -0
- package/src/form-renderer/common/props-forwarder.js +123 -0
- package/src/{common → form-renderer/common}/utils.d.ts +6 -0
- package/src/form-renderer/form-renderer/custom-widget-resolver.d.ts +17 -0
- package/src/form-renderer/form-renderer/custom-widget-resolver.js +39 -0
- package/src/form-renderer/form-renderer/form-renderer-model.d.ts +125 -0
- package/src/form-renderer/form-renderer/form-renderer.d.ts +373 -0
- package/src/form-renderer/{form-renderer.js → form-renderer/form-renderer.js} +429 -298
- package/src/form-renderer/form-renderer/index.d.ts +7 -0
- package/src/form-renderer/form-renderer/index.js +6 -0
- package/src/form-renderer/{render-form-field.js → form-renderer/render-form-field.js} +154 -25
- package/src/form-renderer/index.d.ts +3 -4
- package/src/form-renderer/index.js +3 -3
- package/src/index.d.ts +1 -4
- package/src/index.js +1 -4
- package/common.d.ts +0 -4
- package/common.js +0 -4
- package/src/form-renderer/form-renderer-model.d.ts +0 -65
- package/src/form-renderer/form-renderer.d.ts +0 -425
- package/styles/bds-lite.css +0 -599
- package/styles/bds-lite.scss +0 -2
- package/styles/bds.css +0 -599
- package/styles/bds.scss +0 -2
- package/styles/bootstrap-dark-lite.css +0 -608
- package/styles/bootstrap-dark-lite.scss +0 -2
- package/styles/bootstrap-dark.css +0 -608
- package/styles/bootstrap-dark.scss +0 -2
- package/styles/bootstrap-lite.css +0 -595
- package/styles/bootstrap-lite.scss +0 -2
- package/styles/bootstrap.css +0 -595
- package/styles/bootstrap.scss +0 -2
- package/styles/bootstrap4-lite.css +0 -595
- package/styles/bootstrap4-lite.scss +0 -2
- package/styles/bootstrap4.css +0 -595
- package/styles/bootstrap4.scss +0 -2
- package/styles/bootstrap5-dark-lite.css +0 -595
- package/styles/bootstrap5-dark-lite.scss +0 -2
- package/styles/bootstrap5-dark.css +0 -595
- package/styles/bootstrap5-dark.scss +0 -2
- package/styles/bootstrap5-lite.css +0 -595
- package/styles/bootstrap5-lite.scss +0 -2
- package/styles/bootstrap5.3-lite.css +0 -679
- package/styles/bootstrap5.3-lite.scss +0 -2
- package/styles/bootstrap5.3.css +0 -679
- package/styles/bootstrap5.3.scss +0 -2
- package/styles/bootstrap5.css +0 -595
- package/styles/bootstrap5.scss +0 -2
- package/styles/fabric-dark-lite.css +0 -608
- package/styles/fabric-dark-lite.scss +0 -2
- package/styles/fabric-dark.css +0 -608
- package/styles/fabric-dark.scss +0 -2
- package/styles/fabric-lite.css +0 -595
- package/styles/fabric-lite.scss +0 -2
- package/styles/fabric.css +0 -595
- package/styles/fabric.scss +0 -2
- package/styles/fluent-dark-lite.css +0 -595
- package/styles/fluent-dark-lite.scss +0 -2
- package/styles/fluent-dark.css +0 -595
- package/styles/fluent-dark.scss +0 -2
- package/styles/fluent-lite.css +0 -595
- package/styles/fluent-lite.scss +0 -2
- package/styles/fluent.css +0 -595
- package/styles/fluent.scss +0 -2
- package/styles/fluent2-lite.css +0 -681
- package/styles/fluent2-lite.scss +0 -2
- package/styles/fluent2.css +0 -681
- package/styles/fluent2.scss +0 -2
- package/styles/form-renderer/_all.scss +0 -2
- package/styles/form-renderer/_bds-definition.scss +0 -8
- package/styles/form-renderer/_bootstrap-dark-definition.scss +0 -8
- package/styles/form-renderer/_bootstrap-definition.scss +0 -8
- package/styles/form-renderer/_bootstrap4-definition.scss +0 -8
- package/styles/form-renderer/_bootstrap5-dark-definition.scss +0 -8
- package/styles/form-renderer/_bootstrap5-definition.scss +0 -8
- package/styles/form-renderer/_bootstrap5.3-definition.scss +0 -8
- package/styles/form-renderer/_fabric-dark-definition.scss +0 -8
- package/styles/form-renderer/_fabric-definition.scss +0 -8
- package/styles/form-renderer/_fluent-dark-definition.scss +0 -8
- package/styles/form-renderer/_fluent-definition.scss +0 -8
- package/styles/form-renderer/_fluent2-definition.scss +0 -8
- package/styles/form-renderer/_highcontrast-definition.scss +0 -8
- package/styles/form-renderer/_highcontrast-light-definition.scss +0 -8
- package/styles/form-renderer/_layout.scss +0 -480
- package/styles/form-renderer/_material-dark-definition.scss +0 -8
- package/styles/form-renderer/_material-definition.scss +0 -8
- package/styles/form-renderer/_material3-dark-definition.scss +0 -8
- package/styles/form-renderer/_material3-definition.scss +0 -8
- package/styles/form-renderer/_mixin.scss +0 -26
- package/styles/form-renderer/_tailwind-dark-definition.scss +0 -8
- package/styles/form-renderer/_tailwind-definition.scss +0 -8
- package/styles/form-renderer/_tailwind3-definition.scss +0 -8
- package/styles/form-renderer/_theme.scss +0 -69
- package/styles/form-renderer/_variables.scss +0 -2
- package/styles/form-renderer/bds.css +0 -599
- package/styles/form-renderer/bds.scss +0 -2
- package/styles/form-renderer/bootstrap-dark.css +0 -608
- package/styles/form-renderer/bootstrap-dark.scss +0 -2
- package/styles/form-renderer/bootstrap.css +0 -595
- package/styles/form-renderer/bootstrap.scss +0 -2
- package/styles/form-renderer/bootstrap4.css +0 -595
- package/styles/form-renderer/bootstrap4.scss +0 -2
- package/styles/form-renderer/bootstrap5-dark.css +0 -595
- package/styles/form-renderer/bootstrap5-dark.scss +0 -2
- package/styles/form-renderer/bootstrap5.3.css +0 -679
- package/styles/form-renderer/bootstrap5.3.scss +0 -2
- package/styles/form-renderer/bootstrap5.css +0 -595
- package/styles/form-renderer/bootstrap5.scss +0 -2
- package/styles/form-renderer/fabric-dark.css +0 -608
- package/styles/form-renderer/fabric-dark.scss +0 -2
- package/styles/form-renderer/fabric.css +0 -595
- package/styles/form-renderer/fabric.scss +0 -2
- package/styles/form-renderer/fluent-dark.css +0 -595
- package/styles/form-renderer/fluent-dark.scss +0 -2
- package/styles/form-renderer/fluent.css +0 -595
- package/styles/form-renderer/fluent.scss +0 -2
- package/styles/form-renderer/fluent2.css +0 -681
- package/styles/form-renderer/fluent2.scss +0 -2
- package/styles/form-renderer/highcontrast-light.css +0 -595
- package/styles/form-renderer/highcontrast-light.scss +0 -2
- package/styles/form-renderer/highcontrast.css +0 -608
- package/styles/form-renderer/highcontrast.scss +0 -2
- package/styles/form-renderer/material-dark.css +0 -608
- package/styles/form-renderer/material-dark.scss +0 -2
- package/styles/form-renderer/material.css +0 -595
- package/styles/form-renderer/material.scss +0 -2
- package/styles/form-renderer/material3-dark.css +0 -677
- package/styles/form-renderer/material3-dark.scss +0 -2
- package/styles/form-renderer/material3.css +0 -679
- package/styles/form-renderer/material3.scss +0 -2
- package/styles/form-renderer/tailwind-dark.css +0 -595
- package/styles/form-renderer/tailwind-dark.scss +0 -2
- package/styles/form-renderer/tailwind.css +0 -595
- package/styles/form-renderer/tailwind.scss +0 -2
- package/styles/form-renderer/tailwind3.css +0 -669
- package/styles/form-renderer/tailwind3.scss +0 -2
- package/styles/highcontrast-light-lite.css +0 -595
- package/styles/highcontrast-light-lite.scss +0 -2
- package/styles/highcontrast-light.css +0 -595
- package/styles/highcontrast-light.scss +0 -2
- package/styles/highcontrast-lite.css +0 -608
- package/styles/highcontrast-lite.scss +0 -2
- package/styles/highcontrast.css +0 -608
- package/styles/highcontrast.scss +0 -2
- package/styles/material-dark-lite.css +0 -608
- package/styles/material-dark-lite.scss +0 -2
- package/styles/material-dark.css +0 -608
- package/styles/material-dark.scss +0 -2
- package/styles/material-lite.css +0 -595
- package/styles/material-lite.scss +0 -2
- package/styles/material.css +0 -595
- package/styles/material.scss +0 -2
- package/styles/material3-dark-lite.css +0 -677
- package/styles/material3-dark-lite.scss +0 -2
- package/styles/material3-dark.css +0 -677
- package/styles/material3-dark.scss +0 -2
- package/styles/material3-lite.css +0 -679
- package/styles/material3-lite.scss +0 -2
- package/styles/material3.css +0 -679
- package/styles/material3.scss +0 -2
- package/styles/tailwind-dark-lite.css +0 -595
- package/styles/tailwind-dark-lite.scss +0 -2
- package/styles/tailwind-dark.css +0 -595
- package/styles/tailwind-dark.scss +0 -2
- package/styles/tailwind-lite.css +0 -595
- package/styles/tailwind-lite.scss +0 -2
- package/styles/tailwind.css +0 -595
- package/styles/tailwind.scss +0 -2
- package/styles/tailwind3-lite.css +0 -669
- package/styles/tailwind3-lite.scss +0 -2
- package/styles/tailwind3.css +0 -669
- package/styles/tailwind3.scss +0 -2
- /package/src/{common → form-renderer/common}/checkbox-group.d.ts +0 -0
- /package/src/{common → form-renderer/common}/conditional-rule-engine.js +0 -0
- /package/src/{common → form-renderer/common}/custom-validation-engine.js +0 -0
- /package/src/{common → form-renderer/common}/datagrid-component.d.ts +0 -0
- /package/src/{common → form-renderer/common}/datagrid-component.js +0 -0
- /package/src/{common → form-renderer/common}/expressions/dependency-tracker.d.ts +0 -0
- /package/src/{common → form-renderer/common}/expressions/dependency-tracker.js +0 -0
- /package/src/{common → form-renderer/common}/expressions/expression-engine.js +0 -0
- /package/src/{common → form-renderer/common}/expressions/expression-parser.js +0 -0
- /package/src/{common → form-renderer/common}/expressions/grid-expressions.d.ts +0 -0
- /package/src/{common → form-renderer/common}/expressions/grid-expressions.js +0 -0
- /package/src/{common → form-renderer/common}/expressions/index.d.ts +0 -0
- /package/src/{common → form-renderer/common}/expressions/index.js +0 -0
- /package/src/{common → form-renderer/common}/minmax-rule-engine.d.ts +0 -0
- /package/src/{common → form-renderer/common}/minmax-rule-engine.js +0 -0
- /package/src/{common → form-renderer/common}/option-fetcher.d.ts +0 -0
- /package/src/{common → form-renderer/common}/option-fetcher.js +0 -0
- /package/src/{common → form-renderer/common}/parser.d.ts +0 -0
- /package/src/{common → form-renderer/common}/parser.js +0 -0
- /package/src/{common → form-renderer/common}/static-html-renderer.d.ts +0 -0
- /package/src/{common → form-renderer/common}/static-html-renderer.js +0 -0
- /package/src/{common → form-renderer/common}/utils.js +0 -0
- /package/src/form-renderer/{render-form-field.d.ts → form-renderer/render-form-field.d.ts} +0 -0
- /package/src/form-renderer/{types → form-renderer/types}/form-schema.d.ts +0 -0
- /package/src/form-renderer/{types → form-renderer/types}/form-schema.js +0 -0
|
@@ -28,23 +28,22 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
28
28
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
29
29
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
30
30
|
};
|
|
31
|
-
import { Component, Property, Event, NotifyPropertyChanges, enableRipple, createElement, isNullOrUndefined, L10n, getComponent, addClass } from '@syncfusion/ej2-base';
|
|
31
|
+
import { Component, Collection, Property, Event, NotifyPropertyChanges, enableRipple, createElement, ChildProperty, isNullOrUndefined, L10n, getComponent, addClass, compile, SanitizeHtmlHelper } from '@syncfusion/ej2-base';
|
|
32
32
|
import { Tab } from '@syncfusion/ej2-navigations';
|
|
33
33
|
import { Tooltip } from '@syncfusion/ej2-popups';
|
|
34
34
|
import { FormValidator } from '@syncfusion/ej2-inputs';
|
|
35
35
|
import { renderFormField } from './render-form-field';
|
|
36
|
-
import {
|
|
36
|
+
import { resolveCustomWidget } from './custom-widget-resolver';
|
|
37
|
+
import { mergeSchema, inferTypeFromWidget } from '../common/json-converter';
|
|
37
38
|
import { UniversalJsonParser } from '../common/parser';
|
|
38
39
|
import { VALIDATION_REGEX, formatDateValues, splitWidths } from '../common/utils';
|
|
39
40
|
import StaticHtmlRenderer from '../common/static-html-renderer';
|
|
40
|
-
import { ConditionalRuleEngine } from '../common/
|
|
41
|
+
import { ConditionalRuleEngine } from '../common/index';
|
|
41
42
|
import { ExpressionEngine } from '../common/expressions/expression-engine';
|
|
42
43
|
import { MinMaxRuleEngine } from '../common/minmax-rule-engine';
|
|
43
44
|
import { CustomValidationEngine } from '../common/custom-validation-engine';
|
|
44
45
|
/**
|
|
45
46
|
* @private
|
|
46
|
-
*
|
|
47
|
-
* Internal input target types array to define a target.
|
|
48
47
|
*/
|
|
49
48
|
var inputTargetTypes = [
|
|
50
49
|
'textbox',
|
|
@@ -68,6 +67,29 @@ var inputTargetTypes = [
|
|
|
68
67
|
export var defaultLocale = {
|
|
69
68
|
"unsupportedComponent": "Unsupported Component type"
|
|
70
69
|
};
|
|
70
|
+
/**
|
|
71
|
+
* Specifies the custom widget settings for rendering custom templates for existing FormComponentTypes.
|
|
72
|
+
*/
|
|
73
|
+
var CustomWidgetSetting = /** @class */ (function (_super) {
|
|
74
|
+
__extends(CustomWidgetSetting, _super);
|
|
75
|
+
function CustomWidgetSetting() {
|
|
76
|
+
return _super !== null && _super.apply(this, arguments) || this;
|
|
77
|
+
}
|
|
78
|
+
__decorate([
|
|
79
|
+
Property(null)
|
|
80
|
+
], CustomWidgetSetting.prototype, "template", void 0);
|
|
81
|
+
__decorate([
|
|
82
|
+
Property('')
|
|
83
|
+
], CustomWidgetSetting.prototype, "type", void 0);
|
|
84
|
+
__decorate([
|
|
85
|
+
Property('')
|
|
86
|
+
], CustomWidgetSetting.prototype, "templateId", void 0);
|
|
87
|
+
__decorate([
|
|
88
|
+
Property('')
|
|
89
|
+
], CustomWidgetSetting.prototype, "fieldName", void 0);
|
|
90
|
+
return CustomWidgetSetting;
|
|
91
|
+
}(ChildProperty));
|
|
92
|
+
export { CustomWidgetSetting };
|
|
71
93
|
/**
|
|
72
94
|
* The FormRenderer component consumes a JSON form schema and renders a fully functional, Syncfusion-based form. It handles field mapping, conditional visibility/disabling, expression evaluation, custom validation, and data submission.
|
|
73
95
|
*
|
|
@@ -82,131 +104,57 @@ export var defaultLocale = {
|
|
|
82
104
|
var FormRenderer = /** @class */ (function (_super) {
|
|
83
105
|
__extends(FormRenderer, _super);
|
|
84
106
|
/**
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
* @param {FormRendererModel} options - Specifies the form renderer model
|
|
88
|
-
* @param {string|HTMLDivElement} element - Specifies the target element
|
|
107
|
+
* @private
|
|
89
108
|
*/
|
|
90
109
|
function FormRenderer(options, element) {
|
|
91
110
|
var _this = _super.call(this, options, element) || this;
|
|
92
111
|
_this.processedSchemaCache = { version: '1.0.0', components: [] };
|
|
93
|
-
/** Localization instance */
|
|
94
112
|
_this.l10n = new L10n('form-renderer', defaultLocale, _this.locale);
|
|
95
113
|
/**
|
|
96
114
|
* @private
|
|
97
|
-
*
|
|
98
|
-
* Minimal form-state container owned by the orchestrator. The previous
|
|
99
|
-
* vanilla-TS port delegated this to `FormStateBridge`; that bridge's
|
|
100
|
-
* `registeredFields` gate silently short-circuited every field to "no
|
|
101
|
-
* error" because the orchestrator never called `registerField`. The
|
|
102
|
-
* EJ2 native `FormValidator` (bound to `this.element`) now handles all
|
|
103
|
-
* rule evaluation, error-element placement, change/blur/submit wiring,
|
|
104
|
-
* and ARIA — exactly what `FormValidator` was designed for. This object
|
|
105
|
-
* is the orchestrator's authoritative values store; `errors` are
|
|
106
|
-
* mirrored from the FormValidator's `errorRules` for `renderField`'s
|
|
107
|
-
* initial-paint logic and for submit-time `isValid` checks.
|
|
108
115
|
*/
|
|
109
116
|
_this.formState = { values: Object.create(null), errors: Object.create(null) };
|
|
110
|
-
/** EJ2 native FormValidator bound to `this.element` (replaces FormStateBridge). */
|
|
111
117
|
_this.validator = null;
|
|
112
|
-
/** Map of input component instances keyed by `name` (or `${name}_${idx}`). */
|
|
113
118
|
_this.inputRefs = {};
|
|
114
|
-
/** Conditional value applied tracker (per-field). */
|
|
115
119
|
_this.conditionalValueApplied = {};
|
|
116
|
-
/** Expression engine + dependency graph + computed-field set. */
|
|
117
120
|
_this.expressionEngine = null;
|
|
118
121
|
_this.expressionDependencyGraph = {};
|
|
119
122
|
_this.expressionEvaluationInProgress = false;
|
|
120
123
|
_this.previousFormValues = {};
|
|
121
124
|
_this.computedFieldNames = new Set();
|
|
122
|
-
/** Custom validation engine instance. */
|
|
123
125
|
_this.customValidationEngine = new CustomValidationEngine();
|
|
124
|
-
/** Latest form values snapshot for custom validation (named-key context). */
|
|
125
126
|
_this.currentFormValues = {};
|
|
126
|
-
/** Whether initial values have been seeded once. */
|
|
127
127
|
_this.isInitialized = false;
|
|
128
|
-
/** Cached layout detection result. */
|
|
129
128
|
_this.hasLayoutComponentsCache = false;
|
|
130
|
-
/** Cached id→label map. */
|
|
131
129
|
_this.idToLabelCache = {};
|
|
132
|
-
/** Cached initial values (recomputed on schema change). */
|
|
133
130
|
_this.initialValuesCache = {};
|
|
134
|
-
/** Rendered child EJ2 instances (for destroy cleanup). */
|
|
135
131
|
_this.renderedInstances = [];
|
|
136
|
-
/** Tooltip instances keyed by field id so stale tooltips can be replaced promptly. */
|
|
137
132
|
_this.tooltipRefs = {};
|
|
138
|
-
/** `created` fired-once guard. */
|
|
139
133
|
_this.createdFired = false;
|
|
140
|
-
/**
|
|
141
|
-
* Coalescing guard for `scheduleRerender`. Prevents redundant full-form
|
|
142
|
-
* re-renders within a single microtask — mirrors React's batched-state
|
|
143
|
-
* semantics so that a user keystroke + expression cascade fire one render.
|
|
144
|
-
*/
|
|
145
134
|
_this.rerenderScheduled = false;
|
|
146
|
-
/**
|
|
147
|
-
* Set of `component.id`s that are referenced as the trigger field of any
|
|
148
|
-
* other component's `conditions` (`visibleWhen` / `hideWhen` /
|
|
149
|
-
* `disabledWhen` / `requiredWhen` / `readOnlyWhen` / `setValueWhen` /
|
|
150
|
-
* `choiceBasedField.primaryFieldId`). Only changes to these fields can
|
|
151
|
-
* affect visibility / disabled / required / valueWhen of any other
|
|
152
|
-
* field, so only they need to trigger a full-form re-render. Changes to
|
|
153
|
-
* fields *not* in this set are guaranteed to have no conditional side
|
|
154
|
-
* effects and safely skip the (expensive) full DOM teardown + rebuild.
|
|
155
|
-
* Built once per schema in `buildConditionalDependencyMap`.
|
|
156
|
-
*/
|
|
157
135
|
_this.conditionalTriggerFieldIds = new Set();
|
|
158
|
-
/**
|
|
159
|
-
* Maps `component.id` → the previously-rendered DOM subtree (form-group)
|
|
160
|
-
* for "expensive" components (dataGrid, dropdown, multiselect,
|
|
161
|
-
* checkboxGroup) that support remote data. During a full-form re-render
|
|
162
|
-
* triggered by an *unrelated* conditional change, these subtrees are
|
|
163
|
-
* detached (not destroyed) and re-attached in place, avoiding a re-fetch
|
|
164
|
-
* of their remote data sources and preventing the visible blink/reload.
|
|
165
|
-
* A subtree is *invalidated* (dropped from this map, forcing a fresh
|
|
166
|
-
* render) when a field it depends on (via its own `conditions` or
|
|
167
|
-
* `conditionalData`) is the one that changed.
|
|
168
|
-
*/
|
|
169
136
|
_this.preservedFields = new Map();
|
|
170
|
-
/**
|
|
171
|
-
* Per-consumer dependency map: `component.id` → set of trigger field ids
|
|
172
|
-
* that the consumer's own `conditions` / `conditionalData` /
|
|
173
|
-
* `choiceBasedField` reference. Used during `rerenderForm` to decide
|
|
174
|
-
* whether a preserved subtree must be invalidated (rebuilt) because the
|
|
175
|
-
* changed field is one of its own dependencies, or can be safely reused.
|
|
176
|
-
*/
|
|
177
137
|
_this.consumerDependencyMap = new Map();
|
|
178
138
|
/**
|
|
179
139
|
* @private
|
|
180
|
-
*
|
|
181
|
-
* Coalesced full-form re-render. Multiple triggers within the same
|
|
182
|
-
* microtask drain into a single `rerenderForm()` call. The set of
|
|
183
|
-
* changed field ids is accumulated across the tick so `rerenderForm`
|
|
184
|
-
* can decide which preserved subtrees must be invalidated (because one
|
|
185
|
-
* of the changed fields is in their own dependency set).
|
|
186
140
|
*/
|
|
187
141
|
_this.pendingChangedFieldIds = new Set();
|
|
188
142
|
return _this;
|
|
189
143
|
}
|
|
190
144
|
FormRenderer_1 = FormRenderer;
|
|
191
145
|
/**
|
|
192
|
-
* Returns the EJ2 component module name.
|
|
193
146
|
* @private
|
|
194
147
|
*/
|
|
195
148
|
FormRenderer.prototype.getModuleName = function () {
|
|
196
149
|
return 'form-renderer';
|
|
197
150
|
};
|
|
198
151
|
/**
|
|
199
|
-
* Return the persisted-state payload. The base class declares this
|
|
200
|
-
* abstract; FormRenderer does not implement state persistence, so an
|
|
201
|
-
* empty object is returned (mirrors the EJ2 convention for
|
|
202
|
-
* non-persistent components).
|
|
203
152
|
* @private
|
|
204
153
|
*/
|
|
205
154
|
FormRenderer.prototype.getPersistData = function () {
|
|
206
155
|
return this.addOnPersist(['formState', JSON.stringify(this.formState)]);
|
|
207
156
|
};
|
|
208
157
|
/**
|
|
209
|
-
* Pre-render wiring: enable ripple, init the expression engine + bridge.
|
|
210
158
|
* @private
|
|
211
159
|
*/
|
|
212
160
|
FormRenderer.prototype.preRender = function () {
|
|
@@ -215,7 +163,6 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
215
163
|
this.expressionEngine = new ExpressionEngine();
|
|
216
164
|
};
|
|
217
165
|
/**
|
|
218
|
-
* Main render: normalize schema, build rules + initial values, render tree.
|
|
219
166
|
* @private
|
|
220
167
|
*/
|
|
221
168
|
FormRenderer.prototype.render = function () {
|
|
@@ -237,10 +184,12 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
237
184
|
this.idToLabelCache = this.computeIdToLabel();
|
|
238
185
|
this.initialValuesCache = this.buildInitialValues();
|
|
239
186
|
this.buildValidationRulesAndBridge();
|
|
240
|
-
// Seed initial values into the form-state values map once.
|
|
241
187
|
if (!this.isInitialized) {
|
|
242
188
|
this.isInitialized = true;
|
|
243
189
|
}
|
|
190
|
+
if (this.isReact && this.portals) {
|
|
191
|
+
this.renderReactTemplates();
|
|
192
|
+
}
|
|
244
193
|
if (this.formState && this.initialValuesCache) {
|
|
245
194
|
var initKeys = Object.keys(this.initialValuesCache);
|
|
246
195
|
for (var _i = 0, initKeys_1 = initKeys; _i < initKeys_1.length; _i++) {
|
|
@@ -264,21 +213,7 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
264
213
|
var rendered = _this.renderComponent(component);
|
|
265
214
|
if (rendered) {
|
|
266
215
|
root.appendChild(rendered);
|
|
267
|
-
|
|
268
|
-
if (component.type === 'richTextEditor') {
|
|
269
|
-
var rteElement = rendered.querySelector('.e-richtexteditor');
|
|
270
|
-
var rteInstance = getComponent(rteElement, 'richtexteditor');
|
|
271
|
-
rteInstance.refreshUI();
|
|
272
|
-
}
|
|
273
|
-
if (component.type === 'dataGrid') {
|
|
274
|
-
var toolbarElement = rendered.querySelector('.e-control.e-toolbar');
|
|
275
|
-
var rteInstance = getComponent(toolbarElement, 'toolbar');
|
|
276
|
-
rteInstance.refresh();
|
|
277
|
-
}
|
|
278
|
-
if (component.type === 'tabs') {
|
|
279
|
-
var tabElement = rendered.querySelector('.e-control.e-tab');
|
|
280
|
-
var tabInstance = getComponent(tabElement, 'tab');
|
|
281
|
-
tabInstance.refreshOverflow();
|
|
216
|
+
_this.refreshRenderedComponent(component, rendered);
|
|
282
217
|
}
|
|
283
218
|
});
|
|
284
219
|
if (this.created && !this.createdFired) {
|
|
@@ -290,6 +225,58 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
290
225
|
}, 0);
|
|
291
226
|
}
|
|
292
227
|
};
|
|
228
|
+
FormRenderer.prototype.refreshRenderedComponent = function (component, rendered) {
|
|
229
|
+
var _this = this;
|
|
230
|
+
var componentRoot = rendered;
|
|
231
|
+
if (component.type === 'tabs') {
|
|
232
|
+
componentRoot = rendered.querySelector("#" + component.id + ".e-control.e-tab") || rendered;
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
componentRoot = rendered.querySelector("[data-field-id=\"" + component.id + "\"]") || rendered;
|
|
236
|
+
}
|
|
237
|
+
if (component.type === 'richTextEditor') {
|
|
238
|
+
var rteElement = componentRoot.querySelector('.e-richtexteditor');
|
|
239
|
+
var rteInstance = rteElement ? getComponent(rteElement, 'richtexteditor') : null;
|
|
240
|
+
if (rteInstance) {
|
|
241
|
+
rteInstance.refreshUI();
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
else if (component.type === 'dataGrid') {
|
|
245
|
+
var toolbarElement = componentRoot.querySelector('.e-control.e-toolbar');
|
|
246
|
+
var toolbarInstance = toolbarElement ? getComponent(toolbarElement, 'toolbar') : null;
|
|
247
|
+
if (toolbarInstance) {
|
|
248
|
+
toolbarInstance.refresh();
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
else if (component.type === 'imageEditor') {
|
|
252
|
+
var editorElement = componentRoot.querySelector('.e-control.e-image-editor');
|
|
253
|
+
var editorInstance = editorElement ? getComponent(editorElement, 'image-editor') : null;
|
|
254
|
+
if (editorInstance) {
|
|
255
|
+
editorInstance.refresh();
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
else if (component.type === 'tabs') {
|
|
259
|
+
var tabInstance = getComponent(componentRoot, 'tab');
|
|
260
|
+
if (tabInstance) {
|
|
261
|
+
tabInstance.refreshOverflow();
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
if (component.children) {
|
|
265
|
+
component.children.forEach(function (child) { return _this.refreshRenderedComponent(child, rendered); });
|
|
266
|
+
}
|
|
267
|
+
if (component.tableCells) {
|
|
268
|
+
component.tableCells.forEach(function (row) {
|
|
269
|
+
row.forEach(function (cell) { return cell.forEach(function (child) { return _this.refreshRenderedComponent(child, rendered); }); });
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
if (component.tabItems) {
|
|
273
|
+
component.tabItems.forEach(function (tab) {
|
|
274
|
+
if (tab.content) {
|
|
275
|
+
tab.content.forEach(function (child) { return _this.refreshRenderedComponent(child, rendered); });
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
};
|
|
293
280
|
/**
|
|
294
281
|
* @private
|
|
295
282
|
*/
|
|
@@ -318,7 +305,7 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
318
305
|
var isUnifiedSchema = parsedInput && typeof parsedInput === 'object' &&
|
|
319
306
|
parsedInput.properties && Array.isArray(parsedInput.layout);
|
|
320
307
|
if (isUnifiedSchema) {
|
|
321
|
-
this.processedSchemaCache = mergeSchema(parsedInput);
|
|
308
|
+
this.processedSchemaCache = mergeSchema(parsedInput, this.dataModel || undefined);
|
|
322
309
|
}
|
|
323
310
|
else {
|
|
324
311
|
var parser = new UniversalJsonParser();
|
|
@@ -345,12 +332,7 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
345
332
|
this.processedSchemaCache = { version: '1.0.0', components: [] };
|
|
346
333
|
}
|
|
347
334
|
};
|
|
348
|
-
// ----------------------------------------------------------------------
|
|
349
|
-
// G3 — layout detection + suppression map
|
|
350
|
-
// ----------------------------------------------------------------------
|
|
351
335
|
/**
|
|
352
|
-
* Recursively scan the schema for any `table`/`tabs`/`panel`/`card`
|
|
353
|
-
* (including inside table cells and tab content). Mirrors `hasLayoutComponents`.
|
|
354
336
|
* @private
|
|
355
337
|
*/
|
|
356
338
|
FormRenderer.prototype.computeHasLayoutComponents = function () {
|
|
@@ -392,7 +374,6 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
392
374
|
};
|
|
393
375
|
Object.defineProperty(FormRenderer.prototype, "layoutClass", {
|
|
394
376
|
/**
|
|
395
|
-
* The layout CSS class (suppressed when layout components are present).
|
|
396
377
|
* @private
|
|
397
378
|
*/
|
|
398
379
|
get: function () {
|
|
@@ -414,11 +395,7 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
414
395
|
enumerable: true,
|
|
415
396
|
configurable: true
|
|
416
397
|
});
|
|
417
|
-
// ----------------------------------------------------------------------
|
|
418
|
-
// G4 — collectAllComponents + idToLabel
|
|
419
|
-
// ----------------------------------------------------------------------
|
|
420
398
|
/**
|
|
421
|
-
* Recursively collect all components including nested ones.
|
|
422
399
|
* @private
|
|
423
400
|
*/
|
|
424
401
|
FormRenderer.prototype.collectAllComponents = function (components) {
|
|
@@ -446,6 +423,22 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
446
423
|
traverse(components);
|
|
447
424
|
return all;
|
|
448
425
|
};
|
|
426
|
+
FormRenderer.prototype.getDataModelByName = function () {
|
|
427
|
+
var _this = this;
|
|
428
|
+
var dataModel = {};
|
|
429
|
+
var components = this.collectAllComponents(this.processedSchemaCache.components);
|
|
430
|
+
var componentsById = {};
|
|
431
|
+
components.forEach(function (component) {
|
|
432
|
+
componentsById[component.id] = component;
|
|
433
|
+
});
|
|
434
|
+
Object.keys(this.formState.values).forEach(function (id) {
|
|
435
|
+
var component = componentsById[id];
|
|
436
|
+
if (component && component.name) {
|
|
437
|
+
dataModel[component.name] = _this.formState.values[id];
|
|
438
|
+
}
|
|
439
|
+
});
|
|
440
|
+
return dataModel;
|
|
441
|
+
};
|
|
449
442
|
/**
|
|
450
443
|
* @private
|
|
451
444
|
*/
|
|
@@ -477,10 +470,6 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
477
470
|
traverse(this.processedSchemaCache.components);
|
|
478
471
|
return map;
|
|
479
472
|
};
|
|
480
|
-
// ----------------------------------------------------------------------
|
|
481
|
-
// G5 — buildValidationRules via FormStateBridge + ConditionalRuleEngine +
|
|
482
|
-
// EMAIL/URL auto-regex + customValidator closure
|
|
483
|
-
// ----------------------------------------------------------------------
|
|
484
473
|
/**
|
|
485
474
|
* @private
|
|
486
475
|
*/
|
|
@@ -597,13 +586,11 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
597
586
|
});
|
|
598
587
|
};
|
|
599
588
|
collectRules(this.processedSchemaCache.components);
|
|
600
|
-
// Preserve previously-entered values across a re-render.
|
|
601
589
|
var previousValues = this.formState ? __assign({}, this.formState.values) : __assign({}, this.initialValuesCache);
|
|
602
590
|
this.formState = {
|
|
603
591
|
values: Object.assign(Object.create(null), this.initialValuesCache, previousValues),
|
|
604
592
|
errors: this.enablePersistence ? this.formState.errors : Object.create(null)
|
|
605
593
|
};
|
|
606
|
-
// Restore any previously-entered values that the merge above pruned.
|
|
607
594
|
if (previousValues) {
|
|
608
595
|
Object.keys(previousValues).forEach(function (id) {
|
|
609
596
|
if (!(id in _this.formState.values)) {
|
|
@@ -611,7 +598,6 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
611
598
|
}
|
|
612
599
|
});
|
|
613
600
|
}
|
|
614
|
-
// (Re)create the EJ2 native FormValidator bound to the host element.
|
|
615
601
|
if (this.validator) {
|
|
616
602
|
try {
|
|
617
603
|
this.validator.refresh();
|
|
@@ -630,14 +616,6 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
630
616
|
errorElement: 'div',
|
|
631
617
|
errorContainer: 'div',
|
|
632
618
|
customPlacement: function (inputElement, errorElement) {
|
|
633
|
-
// Locate the per-field error-message slot rendered in
|
|
634
|
-
// `renderField` by its id (`error-<component.id>`). The
|
|
635
|
-
// input's `name` attribute matches `component.id`
|
|
636
|
-
// (set in renderField), so `getElementById('error-' + name)`
|
|
637
|
-
// resolves the slot and the validator's error element is
|
|
638
|
-
// appended into it (FormValidator sets
|
|
639
|
-
// `errorElement.style.display = 'block'` before invoking
|
|
640
|
-
// customPlacement, which makes the slot visible).
|
|
641
619
|
var name = inputElement.getAttribute('name');
|
|
642
620
|
if (!name) {
|
|
643
621
|
if (inputElement.parentElement) {
|
|
@@ -658,15 +636,7 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
658
636
|
}
|
|
659
637
|
},
|
|
660
638
|
validationComplete: function (args) {
|
|
661
|
-
// Mirror the validator's error state into formState.errors so
|
|
662
|
-
// submit-time isValid and renderField's initial-paint logic
|
|
663
|
-
// (which read formState.errors[id]) continue to work.
|
|
664
639
|
self.syncFormStateErrors();
|
|
665
|
-
// Keep the per-field error slot's visibility in sync with
|
|
666
|
-
// the validator's outcome. On `success`, the FormValidator's
|
|
667
|
-
// `hideMessage` sets its own error element's `display: none`,
|
|
668
|
-
// but our slot (`error-<id>`) would otherwise keep the stale
|
|
669
|
-
// error element appended. Clear + hide the slot on success.
|
|
670
640
|
if (args && args.inputName) {
|
|
671
641
|
var slot = document.getElementById("error-" + args.inputName);
|
|
672
642
|
if (slot) {
|
|
@@ -701,10 +671,6 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
701
671
|
reset: function () {
|
|
702
672
|
}
|
|
703
673
|
});
|
|
704
|
-
// Apply cached previous values to the FormValidator's input elements.
|
|
705
|
-
// The validator reads live values from inputs at validate() time, but
|
|
706
|
-
// initial values seeded here ensure any pre-populated values are
|
|
707
|
-
// respected even if a field is never focused before submit.
|
|
708
674
|
if (previousValues) {
|
|
709
675
|
Object.keys(previousValues).forEach(function (id) {
|
|
710
676
|
var inputEl = _this.validator.getInputElement(id);
|
|
@@ -719,10 +685,6 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
719
685
|
};
|
|
720
686
|
/**
|
|
721
687
|
* @private
|
|
722
|
-
*
|
|
723
|
-
* Mirror the FormValidator's `errorRules` array into `this.formState.errors`
|
|
724
|
-
* keyed by field `name` (= `component.id`). Called after every
|
|
725
|
-
* `validationComplete` callback and from submit-time `isValid` reads.
|
|
726
688
|
*/
|
|
727
689
|
FormRenderer.prototype.syncFormStateErrors = function () {
|
|
728
690
|
var errors = {};
|
|
@@ -779,11 +741,7 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
779
741
|
}
|
|
780
742
|
return values;
|
|
781
743
|
};
|
|
782
|
-
// ----------------------------------------------------------------------
|
|
783
|
-
// Expression engine init (used by G9)
|
|
784
|
-
// ----------------------------------------------------------------------
|
|
785
744
|
/**
|
|
786
|
-
* Initialize the expression engine dependency graph + computed-field set.
|
|
787
745
|
* @private
|
|
788
746
|
*/
|
|
789
747
|
FormRenderer.prototype.initExpressionEngine = function () {
|
|
@@ -836,7 +794,7 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
836
794
|
var _this = this;
|
|
837
795
|
var formState = this.formState;
|
|
838
796
|
var formValues = formState ? formState.values : {};
|
|
839
|
-
if (['panel', 'table', 'tabs', 'card', 'message', '
|
|
797
|
+
if (['panel', 'table', 'tabs', 'card', 'message', 'staticHtml'].indexOf(component.type) !== -1) {
|
|
840
798
|
return null;
|
|
841
799
|
}
|
|
842
800
|
var conditionalReadOnly = ConditionalRuleEngine.isFieldReadOnly(component.conditions, formValues);
|
|
@@ -866,7 +824,6 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
866
824
|
var shouldShowError = !!(formState && formState.errors[component.id]);
|
|
867
825
|
var isRequiredError = shouldShowError && !!(formState && formState.errors[component.id].indexOf('required') !== -1);
|
|
868
826
|
var hasError = shouldShowError && !(isRequiredError && !computedRequired);
|
|
869
|
-
// setValueWhen false→true transition tracking.
|
|
870
827
|
var conditionIsActive = conditionalValue !== undefined;
|
|
871
828
|
var wasConditionActive = this.conditionalValueApplied[component.id] || false;
|
|
872
829
|
if (formState) {
|
|
@@ -969,7 +926,7 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
969
926
|
_this.formState.values[component.id] = value;
|
|
970
927
|
formState.values[component.id] = value;
|
|
971
928
|
}
|
|
972
|
-
_this.trigger('change', { fieldName: component.name, label: component.label || component.id, value: value });
|
|
929
|
+
_this.trigger('change', { fieldName: component.name, label: component.label || component.id, value: value, dataModel: _this.getDataModelByName() });
|
|
973
930
|
_this.afterValueChange(component.id);
|
|
974
931
|
}
|
|
975
932
|
};
|
|
@@ -991,60 +948,145 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
991
948
|
target.setAttribute('name', component.id);
|
|
992
949
|
}
|
|
993
950
|
fieldInput.appendChild(target);
|
|
994
|
-
var
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
951
|
+
var skipDefault = false;
|
|
952
|
+
var resolvedWidget = resolveCustomWidget(component, this.customWidgetSettings);
|
|
953
|
+
if (resolvedWidget) {
|
|
954
|
+
var compiled = null;
|
|
955
|
+
try {
|
|
956
|
+
compiled = this.getTemplateFunction(resolvedWidget.entry.template);
|
|
957
|
+
}
|
|
958
|
+
catch (e) {
|
|
959
|
+
if (this.failure) {
|
|
960
|
+
this.trigger('failure', { error: e });
|
|
961
|
+
}
|
|
962
|
+
compiled = null;
|
|
963
|
+
}
|
|
964
|
+
if (compiled) {
|
|
965
|
+
try {
|
|
966
|
+
if (target.parentNode) {
|
|
967
|
+
target.parentNode.removeChild(target);
|
|
968
|
+
}
|
|
969
|
+
var swappedComponent = Object.assign({}, component, {
|
|
970
|
+
id: component.name,
|
|
971
|
+
name: component.id,
|
|
972
|
+
type: inferTypeFromWidget(component.type),
|
|
973
|
+
widget: component.type
|
|
974
|
+
});
|
|
975
|
+
var renderedOut = compiled({
|
|
976
|
+
fieldData: swappedComponent,
|
|
977
|
+
value: formState ? formState.values[component.id] : undefined,
|
|
978
|
+
}, this, 'customWidgetTemplate' + component.id, (this.element.id || 'form-renderer') + 'customWidgetTemplate', this.isStringTemplate, undefined, fieldInput, this.root);
|
|
979
|
+
var outList = void 0;
|
|
980
|
+
if (renderedOut == null) {
|
|
981
|
+
outList = [];
|
|
982
|
+
}
|
|
983
|
+
else if (Array.isArray(renderedOut)) {
|
|
984
|
+
outList = renderedOut;
|
|
985
|
+
}
|
|
986
|
+
else if (typeof renderedOut === 'string') {
|
|
987
|
+
outList = [renderedOut];
|
|
988
|
+
}
|
|
989
|
+
else if (typeof renderedOut === 'object'
|
|
990
|
+
&& !renderedOut.nodeType
|
|
991
|
+
&& typeof renderedOut.length === 'number'
|
|
992
|
+
&& typeof renderedOut.item === 'function') {
|
|
993
|
+
var snapshot = [];
|
|
994
|
+
var list = renderedOut;
|
|
995
|
+
for (var i = 0; i < list.length; i++) {
|
|
996
|
+
snapshot.push(list[i]);
|
|
1006
997
|
}
|
|
1007
|
-
|
|
1008
|
-
_this.syncFormStateErrors();
|
|
998
|
+
outList = snapshot;
|
|
1009
999
|
}
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
_this.renderedInstances.push(inst);
|
|
1000
|
+
else {
|
|
1001
|
+
outList = [renderedOut];
|
|
1002
|
+
}
|
|
1003
|
+
for (var _i = 0, outList_1 = outList; _i < outList_1.length; _i++) {
|
|
1004
|
+
var node = outList_1[_i];
|
|
1005
|
+
if (node && typeof node === 'object' && node.nodeType) {
|
|
1006
|
+
fieldInput.appendChild(node);
|
|
1007
|
+
}
|
|
1008
|
+
else if (typeof node === 'string') {
|
|
1009
|
+
var markup = this.sanitizeTemplateValue(node);
|
|
1010
|
+
var span = createElement('span');
|
|
1011
|
+
span.innerHTML = markup;
|
|
1012
|
+
while (span.firstChild) {
|
|
1013
|
+
fieldInput.appendChild(span.firstChild);
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
else if (node && typeof node === 'object') {
|
|
1017
|
+
throw new Error('Custom widget template for "' + component.name + '" returned a ' +
|
|
1018
|
+
'framework object that the vanilla renderer cannot insert. Use the ' +
|
|
1019
|
+
'React/Angular/Vue wrapper (registered templates / portals) for ' +
|
|
1020
|
+
'JSX or platform templates.');
|
|
1032
1021
|
}
|
|
1033
1022
|
}
|
|
1023
|
+
setInputRef(fieldInput);
|
|
1024
|
+
skipDefault = true;
|
|
1034
1025
|
}
|
|
1026
|
+
catch (renderErr) {
|
|
1027
|
+
if (this.failure) {
|
|
1028
|
+
this.trigger('failure', { error: renderErr });
|
|
1029
|
+
}
|
|
1030
|
+
skipDefault = false;
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
if (!skipDefault) {
|
|
1035
|
+
var instance = renderFormField({
|
|
1036
|
+
component: mergedComponent,
|
|
1037
|
+
value: formState ? formState.values[component.id] : undefined,
|
|
1038
|
+
onChange: onChangeHandler,
|
|
1039
|
+
formState: formState,
|
|
1040
|
+
settings: this.processedSchemaCache.settings,
|
|
1041
|
+
onBlur: function () {
|
|
1042
|
+
if (formState && component.type !== 'staticHtml') {
|
|
1043
|
+
if (_this.validator) {
|
|
1044
|
+
try {
|
|
1045
|
+
_this.beforeValidate(component.id);
|
|
1046
|
+
_this.validator.validate(component.id);
|
|
1047
|
+
}
|
|
1048
|
+
catch (e) { /* swallow */ }
|
|
1049
|
+
_this.syncFormStateErrors();
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
},
|
|
1053
|
+
ref: setInputRef,
|
|
1054
|
+
hasError: hasError,
|
|
1055
|
+
locale: this.locale,
|
|
1056
|
+
components: this.collectAllComponents(this.processedSchemaCache.components),
|
|
1057
|
+
enableRtl: this.enableRtl,
|
|
1058
|
+
target: target,
|
|
1059
|
+
l10n: this.l10n
|
|
1035
1060
|
});
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1061
|
+
if (Array.isArray(instance)) {
|
|
1062
|
+
instance.forEach(function (entry) {
|
|
1063
|
+
if (entry && typeof entry.destroy === 'function') {
|
|
1064
|
+
_this.renderedInstances.push(entry);
|
|
1065
|
+
}
|
|
1066
|
+
else if (entry instanceof HTMLElement) {
|
|
1067
|
+
for (var _i = 0, _a = Object.keys(_this.inputRefs); _i < _a.length; _i++) {
|
|
1068
|
+
var key = _a[_i];
|
|
1069
|
+
var inst = _this.inputRefs[key];
|
|
1070
|
+
var hostEl = inst && (inst.element || inst.target || (inst.hostElement && inst.hostElement()));
|
|
1071
|
+
if (hostEl && (hostEl === entry || entry.contains(hostEl))) {
|
|
1072
|
+
_this.renderedInstances.push(inst);
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
});
|
|
1077
|
+
}
|
|
1078
|
+
else if (instance) {
|
|
1079
|
+
if (typeof instance.destroy === 'function') {
|
|
1080
|
+
this.renderedInstances.push(instance);
|
|
1081
|
+
}
|
|
1082
|
+
else if (instance instanceof HTMLElement) {
|
|
1083
|
+
for (var _a = 0, _b = Object.keys(this.inputRefs); _a < _b.length; _a++) {
|
|
1084
|
+
var key = _b[_a];
|
|
1085
|
+
var inst = this.inputRefs[key];
|
|
1086
|
+
var hostEl = inst && (inst.element || inst.target || (inst.hostElement && inst.hostElement()));
|
|
1087
|
+
if (hostEl && (hostEl === instance || instance.contains(hostEl))) {
|
|
1088
|
+
this.renderedInstances.push(inst);
|
|
1089
|
+
}
|
|
1048
1090
|
}
|
|
1049
1091
|
}
|
|
1050
1092
|
}
|
|
@@ -1090,11 +1132,6 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
1090
1132
|
}
|
|
1091
1133
|
return null;
|
|
1092
1134
|
}
|
|
1093
|
-
// Re-attach preserved subtree for expensive / remote-data components
|
|
1094
|
-
// (dataGrid / dropdown / multiselect / checkboxGroup / lookup). The
|
|
1095
|
-
// subtree was detached in `rerenderForm` before the rest of the tree
|
|
1096
|
-
// was destroyed; re-attaching it here avoids a re-fetch of remote
|
|
1097
|
-
// data sources and prevents the visible blink of a fresh render.
|
|
1098
1135
|
if (FormRenderer_1.PRESERVABLE_TYPES.has(component.type) && this.preservedFields.has(component.id)) {
|
|
1099
1136
|
var preservedNode = this.preservedFields.get(component.id);
|
|
1100
1137
|
if (preservedNode) {
|
|
@@ -1191,14 +1228,6 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
1191
1228
|
tabHost.appendChild(tabHeader_1);
|
|
1192
1229
|
tabHost.appendChild(tabContent_1);
|
|
1193
1230
|
tabsDiv.appendChild(tabHost);
|
|
1194
|
-
// Build the tab's host DOM up front so each `.e-content > .e-item`
|
|
1195
|
-
// wrapper exists during initialization. Using the JSON `items`
|
|
1196
|
-
// path causes EJ2 to lazily materialize only the active content
|
|
1197
|
-
// panel, which leaves the remaining rendered tab bodies missing
|
|
1198
|
-
// from the live DOM. By seeding the HTML markup structure and
|
|
1199
|
-
// inserting the already-rendered live child nodes into every
|
|
1200
|
-
// content item, the bound EJ2 instances stay attached and all
|
|
1201
|
-
// tabs render correctly.
|
|
1202
1231
|
(component.tabItems || []).forEach(function (tab) {
|
|
1203
1232
|
var headerItem = createElement('div');
|
|
1204
1233
|
headerItem.textContent = tab.header;
|
|
@@ -1308,6 +1337,9 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
1308
1337
|
return wrapper;
|
|
1309
1338
|
}
|
|
1310
1339
|
case 'button': {
|
|
1340
|
+
if (resolveCustomWidget(component, this.customWidgetSettings)) {
|
|
1341
|
+
return this.renderField(component);
|
|
1342
|
+
}
|
|
1311
1343
|
var buttonlDisabled = ConditionalRuleEngine.isFieldDisabled(component.conditions, formValues);
|
|
1312
1344
|
var buttonComputed = !!component.disabled || buttonlDisabled;
|
|
1313
1345
|
var wrapper = createElement('div', { className: 'form-group' });
|
|
@@ -1332,6 +1364,12 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
1332
1364
|
form.querySelectorAll('.e-control.e-multiselect.e-lib').forEach(function (cb) {
|
|
1333
1365
|
(cb.ej2_instances[0]).value = [];
|
|
1334
1366
|
});
|
|
1367
|
+
form.querySelectorAll('.e-control.e-slider.e-lib').forEach(function (slider) {
|
|
1368
|
+
(slider.ej2_instances[0]).value = 0;
|
|
1369
|
+
});
|
|
1370
|
+
form.querySelectorAll('.e-control.e-uploader.e-lib').forEach(function (upload) {
|
|
1371
|
+
(upload.ej2_instances[0]).clearAll();
|
|
1372
|
+
});
|
|
1335
1373
|
}
|
|
1336
1374
|
_this.formState.values = {};
|
|
1337
1375
|
form.reset();
|
|
@@ -1369,6 +1407,9 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
1369
1407
|
return wrapper;
|
|
1370
1408
|
}
|
|
1371
1409
|
case 'splitButton': {
|
|
1410
|
+
if (resolveCustomWidget(component, this.customWidgetSettings)) {
|
|
1411
|
+
return this.renderField(component);
|
|
1412
|
+
}
|
|
1372
1413
|
var splitButtonDisabled = ConditionalRuleEngine.isFieldDisabled(component.conditions, formValues);
|
|
1373
1414
|
var computedDisabled = !!component.disabled || splitButtonDisabled;
|
|
1374
1415
|
var wrapper = createElement('div', { className: 'form-group' });
|
|
@@ -1422,11 +1463,6 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
1422
1463
|
this.beforeValidate(changedFieldId);
|
|
1423
1464
|
this.validator.validate(changedFieldId);
|
|
1424
1465
|
this.syncFormStateErrors();
|
|
1425
|
-
// Only schedule a full-form re-render when the changed field is a
|
|
1426
|
-
// conditional trigger (i.e. some other field's visibility/disabled/
|
|
1427
|
-
// required/readOnly/valueWhen references its id). Changes to fields
|
|
1428
|
-
// that nothing depends on skip the expensive DOM teardown + rebuild,
|
|
1429
|
-
// keeping keystroke latency low for non-conditional inputs.
|
|
1430
1466
|
if (changedFieldId && this.isConditionalTrigger(changedFieldId)) {
|
|
1431
1467
|
this.scheduleRerender(changedFieldId);
|
|
1432
1468
|
}
|
|
@@ -1440,8 +1476,12 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
1440
1476
|
infoElement.classList.remove('e-error');
|
|
1441
1477
|
}
|
|
1442
1478
|
var inputElement = this.getInputElementByName(fieldId);
|
|
1479
|
+
if (!inputElement) {
|
|
1480
|
+
return;
|
|
1481
|
+
}
|
|
1443
1482
|
var inputParent = inputElement.parentElement;
|
|
1444
1483
|
var grandParent = inputParent.parentElement;
|
|
1484
|
+
var greatGrandParent = grandParent ? grandParent.parentElement : null;
|
|
1445
1485
|
if (inputParent.classList.contains('e-control-wrapper') || inputParent.classList.contains('e-wrapper') ||
|
|
1446
1486
|
(inputElement.classList.contains('e-input') && inputParent.classList.contains('e-input-group'))) {
|
|
1447
1487
|
inputParent.classList.remove('e-error');
|
|
@@ -1449,6 +1489,9 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
1449
1489
|
else if ((grandParent != null) && (grandParent.classList.contains('e-control-wrapper') || grandParent.classList.contains('e-wrapper'))) {
|
|
1450
1490
|
grandParent.classList.remove('e-error');
|
|
1451
1491
|
}
|
|
1492
|
+
else if ((greatGrandParent != null) && (greatGrandParent.classList.contains('e-control-wrapper') || greatGrandParent.classList.contains('e-wrapper'))) {
|
|
1493
|
+
greatGrandParent.classList.remove('e-error');
|
|
1494
|
+
}
|
|
1452
1495
|
else {
|
|
1453
1496
|
inputElement.classList.remove('e-error');
|
|
1454
1497
|
}
|
|
@@ -1474,23 +1517,15 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
1474
1517
|
};
|
|
1475
1518
|
/**
|
|
1476
1519
|
* @private
|
|
1477
|
-
*
|
|
1478
|
-
* Recursively walk a `ConditionType` (a `ConditionalRule { field }` leaf
|
|
1479
|
-
* or a `CompositeConditionalRule { rules: [...] }` tree) and collect the
|
|
1480
|
-
* `field` ids of every leaf rule into the supplied `acc` set. These are
|
|
1481
|
-
* the trigger ids whose value changes can affect the visibility/disabled/
|
|
1482
|
-
* required/readOnly/valueWhen of the component that owns this `conditions`.
|
|
1483
1520
|
*/
|
|
1484
1521
|
FormRenderer.prototype.collectConditionFieldIds = function (condition, acc) {
|
|
1485
1522
|
if (!condition) {
|
|
1486
1523
|
return;
|
|
1487
1524
|
}
|
|
1488
1525
|
if (typeof condition.field === 'string') {
|
|
1489
|
-
// Leaf rule.
|
|
1490
1526
|
acc.add(condition.field);
|
|
1491
1527
|
}
|
|
1492
1528
|
else if (Array.isArray(condition.rules)) {
|
|
1493
|
-
// Composite (and/or) — recurse.
|
|
1494
1529
|
for (var _i = 0, _a = condition.rules; _i < _a.length; _i++) {
|
|
1495
1530
|
var sub = _a[_i];
|
|
1496
1531
|
this.collectConditionFieldIds(sub, acc);
|
|
@@ -1519,18 +1554,9 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
1519
1554
|
};
|
|
1520
1555
|
/**
|
|
1521
1556
|
* @private
|
|
1522
|
-
*
|
|
1523
|
-
* Build `this.conditionalTriggerFieldIds` — the set of every
|
|
1524
|
-
* `component.id` that is referenced by *any* other component's
|
|
1525
|
-
* `conditions` (visibleWhen / hideWhen / disabledWhen / requiredWhen /
|
|
1526
|
-
* readOnlyWhen / setValueWhen / choiceBasedField.primaryFieldId).
|
|
1527
|
-
* Only changes to ids in this set can affect another field's
|
|
1528
|
-
* visibility/enabled/required/value, so only they need to trigger a
|
|
1529
|
-
* full-form re-render. Called once per schema during `render()`.
|
|
1530
1557
|
*/
|
|
1531
1558
|
FormRenderer.prototype.buildConditionalDependencyMap = function () {
|
|
1532
1559
|
var triggers = new Set();
|
|
1533
|
-
// Per-consumer dependency set (rebuilt each pass).
|
|
1534
1560
|
var consumerDeps = new Map();
|
|
1535
1561
|
var allComps = this.collectAllComponents(this.processedSchemaCache.components);
|
|
1536
1562
|
var _loop_3 = function (comp) {
|
|
@@ -1561,7 +1587,6 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
1561
1587
|
this_1.collectConditionFieldIds(item.condition, triggers);
|
|
1562
1588
|
this_1.collectConditionFieldIds(item.condition, myDeps);
|
|
1563
1589
|
}
|
|
1564
|
-
// DataGrid conditional columns
|
|
1565
1590
|
if (item && Array.isArray(item.conditions)) {
|
|
1566
1591
|
for (var _c = 0, _d = item.conditions; _c < _d.length; _c++) {
|
|
1567
1592
|
var subCond = _d[_c];
|
|
@@ -1609,13 +1634,6 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
1609
1634
|
collectMinMaxReferenceIds(range);
|
|
1610
1635
|
}
|
|
1611
1636
|
}
|
|
1612
|
-
// ==========================================================
|
|
1613
|
-
// DataGrid remote datasource dependencies
|
|
1614
|
-
// Example:
|
|
1615
|
-
// search.key = "{combobox}"
|
|
1616
|
-
// filter.value = "{department}"
|
|
1617
|
-
// Resolve component by NAME and add its ID as dependency.
|
|
1618
|
-
// ==========================================================
|
|
1619
1637
|
var ds = comp.dataSource;
|
|
1620
1638
|
if ((comp.type === 'dataGrid') &&
|
|
1621
1639
|
ds &&
|
|
@@ -1645,26 +1663,29 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
1645
1663
|
};
|
|
1646
1664
|
/**
|
|
1647
1665
|
* @private
|
|
1648
|
-
*
|
|
1649
|
-
* Returns `true` if a value change to `fieldId` can affect any other
|
|
1650
|
-
* field's conditional state (visibility/disabled/required/readOnly/
|
|
1651
|
-
* valueWhen/choiceBasedField) — i.e. `fieldId` is in the
|
|
1652
|
-
* `conditionalTriggerFieldIds` set built by
|
|
1653
|
-
* `buildConditionalDependencyMap`. Used by `afterValueChange` to skip
|
|
1654
|
-
* the expensive full-form re-render when the changed field is not a
|
|
1655
|
-
* conditional trigger.
|
|
1656
1666
|
*/
|
|
1657
1667
|
FormRenderer.prototype.isConditionalTrigger = function (fieldId) {
|
|
1658
1668
|
return this.conditionalTriggerFieldIds.has(fieldId);
|
|
1659
1669
|
};
|
|
1670
|
+
FormRenderer.prototype.getScrollParent = function () {
|
|
1671
|
+
var parent = this.element.parentElement;
|
|
1672
|
+
while (parent) {
|
|
1673
|
+
var style = window.getComputedStyle(parent);
|
|
1674
|
+
var overflowY = style.overflowY;
|
|
1675
|
+
var overflowX = style.overflowX;
|
|
1676
|
+
var canScrollY = (overflowY === 'auto' || overflowY === 'scroll' || overflowY === 'overlay') &&
|
|
1677
|
+
parent.scrollHeight > parent.clientHeight;
|
|
1678
|
+
var canScrollX = (overflowX === 'auto' || overflowX === 'scroll' || overflowX === 'overlay') &&
|
|
1679
|
+
parent.scrollWidth > parent.clientWidth;
|
|
1680
|
+
if (canScrollY || canScrollX) {
|
|
1681
|
+
return parent;
|
|
1682
|
+
}
|
|
1683
|
+
parent = parent.parentElement;
|
|
1684
|
+
}
|
|
1685
|
+
return null;
|
|
1686
|
+
};
|
|
1660
1687
|
/**
|
|
1661
1688
|
* @private
|
|
1662
|
-
*
|
|
1663
|
-
* Tear down the rendered tree and re-render it, preserving user-entered
|
|
1664
|
-
* `formState.values` (carried through `buildValidationRulesAndBridge`'s
|
|
1665
|
-
* `previousValues` merge) and restoring keyboard focus to the field that
|
|
1666
|
-
* had it before re-render (so a user typing in a textbox is not
|
|
1667
|
-
* interrupted by a dependent field appearing/disappearing on the page).
|
|
1668
1689
|
*/
|
|
1669
1690
|
FormRenderer.prototype.rerenderForm = function (changedFieldIds) {
|
|
1670
1691
|
var _this = this;
|
|
@@ -1680,12 +1701,15 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
1680
1701
|
selectionStart = activeEl.selectionStart;
|
|
1681
1702
|
selectionEnd = activeEl.selectionEnd;
|
|
1682
1703
|
}
|
|
1683
|
-
catch (e) { /*
|
|
1704
|
+
catch (e) { /* ignore */ }
|
|
1684
1705
|
}
|
|
1685
1706
|
var savedElementScrollTop = this.element.scrollTop;
|
|
1686
1707
|
var savedElementScrollLeft = this.element.scrollLeft;
|
|
1687
1708
|
var savedWindowScrollX = window.scrollX;
|
|
1688
1709
|
var savedWindowScrollY = window.scrollY;
|
|
1710
|
+
var scrollParent = this.getScrollParent();
|
|
1711
|
+
var savedScrollParentTop = scrollParent ? scrollParent.scrollTop : 0;
|
|
1712
|
+
var savedScrollParentLeft = scrollParent ? scrollParent.scrollLeft : 0;
|
|
1689
1713
|
this.preservedFields.clear();
|
|
1690
1714
|
var allComps = this.collectAllComponents(this.processedSchemaCache.components);
|
|
1691
1715
|
var _loop_4 = function (comp) {
|
|
@@ -1716,6 +1740,9 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
1716
1740
|
_loop_4(comp);
|
|
1717
1741
|
}
|
|
1718
1742
|
this.refreshing = true;
|
|
1743
|
+
if (this.isReact || this.isAngular) {
|
|
1744
|
+
this.clearTemplate();
|
|
1745
|
+
}
|
|
1719
1746
|
this.destroyRenderedExcludingPreserved();
|
|
1720
1747
|
this.removePreviousRoot();
|
|
1721
1748
|
if (this.validator) {
|
|
@@ -1726,6 +1753,10 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
1726
1753
|
try {
|
|
1727
1754
|
this.element.scrollTop = savedElementScrollTop;
|
|
1728
1755
|
this.element.scrollLeft = savedElementScrollLeft;
|
|
1756
|
+
if (scrollParent) {
|
|
1757
|
+
scrollParent.scrollTop = savedScrollParentTop;
|
|
1758
|
+
scrollParent.scrollLeft = savedScrollParentLeft;
|
|
1759
|
+
}
|
|
1729
1760
|
window.scrollTo(savedWindowScrollX, savedWindowScrollY);
|
|
1730
1761
|
}
|
|
1731
1762
|
catch (e) { /* swallow */ }
|
|
@@ -1745,15 +1776,9 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
1745
1776
|
catch (e) { /* swallow */ }
|
|
1746
1777
|
}
|
|
1747
1778
|
}
|
|
1748
|
-
// Drop preserved subtrees that were not re-attached (e.g. their
|
|
1749
|
-
// field became hidden during this re-render). Their EJ2 instances
|
|
1750
|
-
// are still in `renderedInstances`; destroy them now to avoid leaks.
|
|
1751
1779
|
if (this.preservedFields.size > 0) {
|
|
1752
1780
|
var stillKept_1 = [];
|
|
1753
1781
|
this.preservedFields.forEach(function (node, id) {
|
|
1754
|
-
// If the node is no longer in the live document tree, the
|
|
1755
|
-
// field was not re-attached (hidden / removed). Destroy it
|
|
1756
|
-
// and remove the detached DOM node so it cannot be re-used.
|
|
1757
1782
|
if (!_this.element.contains(node) && !document.body.contains(node)) {
|
|
1758
1783
|
_this.destroyPreservedSubtree(node);
|
|
1759
1784
|
try {
|
|
@@ -1762,7 +1787,7 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
1762
1787
|
}
|
|
1763
1788
|
}
|
|
1764
1789
|
catch (e) {
|
|
1765
|
-
//
|
|
1790
|
+
// ignore
|
|
1766
1791
|
}
|
|
1767
1792
|
_this.preservedFields.delete(id);
|
|
1768
1793
|
}
|
|
@@ -1816,11 +1841,6 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
1816
1841
|
};
|
|
1817
1842
|
/**
|
|
1818
1843
|
* @private
|
|
1819
|
-
*
|
|
1820
|
-
* Destroy all rendered EJ2 instances except those whose host element
|
|
1821
|
-
* lives inside a preserved subtree (those are kept alive for re-use in
|
|
1822
|
-
* the upcoming `render()` pass). Mirrors `destroyRendered` but skips
|
|
1823
|
-
* instances rooted in `preservedFields` nodes.
|
|
1824
1844
|
*/
|
|
1825
1845
|
FormRenderer.prototype.destroyRenderedExcludingPreserved = function () {
|
|
1826
1846
|
var survived = [];
|
|
@@ -1841,8 +1861,6 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
1841
1861
|
_loop_5(inst);
|
|
1842
1862
|
}
|
|
1843
1863
|
this.renderedInstances = survived;
|
|
1844
|
-
// Prune inputRefs whose host element lives in a destroyed subtree
|
|
1845
|
-
// (preserved ones stay).
|
|
1846
1864
|
var inputRefKeys = Object.keys(this.inputRefs);
|
|
1847
1865
|
var _loop_6 = function (key) {
|
|
1848
1866
|
var inst = this_4.inputRefs[key];
|
|
@@ -1865,10 +1883,6 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
1865
1883
|
};
|
|
1866
1884
|
/**
|
|
1867
1885
|
* @private
|
|
1868
|
-
*
|
|
1869
|
-
* Destroy EJ2 instances whose host element lives inside a preserved
|
|
1870
|
-
* subtree that was NOT re-attached (field became hidden). Used during
|
|
1871
|
-
* the post-render cleanup pass in `rerenderForm`.
|
|
1872
1886
|
*/
|
|
1873
1887
|
FormRenderer.prototype.destroyPreservedSubtree = function (rootNode) {
|
|
1874
1888
|
var survived = [];
|
|
@@ -1898,7 +1912,6 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
1898
1912
|
return inputEl;
|
|
1899
1913
|
};
|
|
1900
1914
|
/**
|
|
1901
|
-
* Evaluate expressions in topological order with type coercion.
|
|
1902
1915
|
* @private
|
|
1903
1916
|
*/
|
|
1904
1917
|
FormRenderer.prototype.evaluateExpressions = function () {
|
|
@@ -1999,22 +2012,10 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
1999
2012
|
}
|
|
2000
2013
|
if (result !== null && result !== undefined && result !== formValues[component.id] && this_5.formState) {
|
|
2001
2014
|
this_5.formState.values[component.id] = result;
|
|
2002
|
-
// Sync the underlying input element so the
|
|
2003
|
-
// FormValidator reads the new value on its
|
|
2004
|
-
// next validate() pass.
|
|
2005
2015
|
if (this_5.validator) {
|
|
2006
2016
|
var inputEl = this_5.getInputElementByName(component.id);
|
|
2007
2017
|
if (inputEl) {
|
|
2008
|
-
|
|
2009
|
-
if (inputEl.ej2_instances[0]) {
|
|
2010
|
-
inputEl.ej2_instances[0].value = result;
|
|
2011
|
-
// (inputEl as any).ej2_instances[0].refresh();
|
|
2012
|
-
}
|
|
2013
|
-
else {
|
|
2014
|
-
(inputEl).value = String(result);
|
|
2015
|
-
}
|
|
2016
|
-
}
|
|
2017
|
-
catch (e) { /* swallow */ }
|
|
2018
|
+
this_5.syncValueToInput(inputEl, component.id, result);
|
|
2018
2019
|
}
|
|
2019
2020
|
}
|
|
2020
2021
|
}
|
|
@@ -2041,7 +2042,6 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
2041
2042
|
}
|
|
2042
2043
|
};
|
|
2043
2044
|
/**
|
|
2044
|
-
* Re-trigger custom validation for changed + dependent fields.
|
|
2045
2045
|
* @private
|
|
2046
2046
|
*/
|
|
2047
2047
|
FormRenderer.prototype.retriggerCustomValidation = function () {
|
|
@@ -2146,13 +2146,106 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
2146
2146
|
}
|
|
2147
2147
|
};
|
|
2148
2148
|
/**
|
|
2149
|
-
* Retrieves the underlying Syncfusion form-input component instance by its field name.
|
|
2149
|
+
* Retrieves the underlying Syncfusion form-input component instance by its field name.
|
|
2150
|
+
* Use this to call Syncfusion component methods and properties.
|
|
2151
|
+
*
|
|
2152
|
+
* @param {string} name - Specifies the name for the built-in Syncfusion component.
|
|
2153
|
+
* @returns {object | null} - Specifies the instance of the Syncfusion component in the form.
|
|
2150
2154
|
*/
|
|
2151
2155
|
FormRenderer.prototype.getComponent = function (name) {
|
|
2152
2156
|
return this.inputRefs[name] || null;
|
|
2153
2157
|
};
|
|
2154
2158
|
/**
|
|
2155
|
-
*
|
|
2159
|
+
* Programmatically sets a form field's value for user edits.
|
|
2160
|
+
*
|
|
2161
|
+
* @param {string} fieldName - The field's `name` (the schema property's `name`).
|
|
2162
|
+
* @param {any} value - The new value to set.
|
|
2163
|
+
* @returns void
|
|
2164
|
+
*/
|
|
2165
|
+
FormRenderer.prototype.setFieldValue = function (fieldName, value) {
|
|
2166
|
+
var allComponents = this.collectAllComponents(this.processedSchemaCache.components || []);
|
|
2167
|
+
var component = allComponents.find(function (c) { return c.name === fieldName; });
|
|
2168
|
+
if (!component) {
|
|
2169
|
+
return;
|
|
2170
|
+
}
|
|
2171
|
+
if (this.formState) {
|
|
2172
|
+
this.formState.values[component.id] = value;
|
|
2173
|
+
}
|
|
2174
|
+
var inputEl = this.getInputElementByName(component.id);
|
|
2175
|
+
if (inputEl) {
|
|
2176
|
+
this.syncValueToInput(inputEl, component.id, value);
|
|
2177
|
+
}
|
|
2178
|
+
this.afterValueChange(component.id);
|
|
2179
|
+
};
|
|
2180
|
+
/**
|
|
2181
|
+
* @private
|
|
2182
|
+
*/
|
|
2183
|
+
FormRenderer.prototype.syncValueToInput = function (inputEl, fieldId, value) {
|
|
2184
|
+
if (!inputEl) {
|
|
2185
|
+
return;
|
|
2186
|
+
}
|
|
2187
|
+
try {
|
|
2188
|
+
var nativeInput = (inputEl instanceof HTMLInputElement) ? inputEl : null;
|
|
2189
|
+
var isCheckable = !!nativeInput &&
|
|
2190
|
+
(nativeInput.type === 'checkbox' || nativeInput.type === 'radio');
|
|
2191
|
+
var ej2Inst = inputEl.ej2_instances && inputEl.ej2_instances[0];
|
|
2192
|
+
if (ej2Inst) {
|
|
2193
|
+
if (isCheckable && typeof ej2Inst.checked !== 'undefined') {
|
|
2194
|
+
if (nativeInput.type === 'radio' && typeof ej2Inst.value !== 'undefined') {
|
|
2195
|
+
ej2Inst.checked = String(value) === String(ej2Inst.value);
|
|
2196
|
+
}
|
|
2197
|
+
else {
|
|
2198
|
+
ej2Inst.checked = FormRenderer_1.coerceChecked(value);
|
|
2199
|
+
}
|
|
2200
|
+
}
|
|
2201
|
+
else if (typeof ej2Inst.value !== 'undefined') {
|
|
2202
|
+
ej2Inst.value = value;
|
|
2203
|
+
}
|
|
2204
|
+
return;
|
|
2205
|
+
}
|
|
2206
|
+
if (inputEl instanceof HTMLSelectElement) {
|
|
2207
|
+
var strValue = (value === null || value === undefined) ? '' : String(value);
|
|
2208
|
+
inputEl.value = strValue;
|
|
2209
|
+
if (inputEl.value !== strValue && inputEl.options.length > 0) {
|
|
2210
|
+
for (var i = 0; i < inputEl.options.length; i++) {
|
|
2211
|
+
if (inputEl.options[i].text === strValue) {
|
|
2212
|
+
inputEl.value = inputEl.options[i].value;
|
|
2213
|
+
break;
|
|
2214
|
+
}
|
|
2215
|
+
}
|
|
2216
|
+
}
|
|
2217
|
+
}
|
|
2218
|
+
else if (nativeInput && nativeInput.type === 'radio') {
|
|
2219
|
+
var radios = this.element.querySelectorAll("input[type=\"radio\"][name=\"" + fieldId + "\"]");
|
|
2220
|
+
for (var i = 0; i < radios.length; i++) {
|
|
2221
|
+
radios[i].checked = String(value) === radios[i].value;
|
|
2222
|
+
}
|
|
2223
|
+
}
|
|
2224
|
+
else if (isCheckable) {
|
|
2225
|
+
nativeInput.checked = FormRenderer_1.coerceChecked(value);
|
|
2226
|
+
}
|
|
2227
|
+
else if (typeof inputEl.value !== 'undefined') {
|
|
2228
|
+
inputEl.value = (value === null || value === undefined) ? '' : String(value);
|
|
2229
|
+
}
|
|
2230
|
+
}
|
|
2231
|
+
catch (e) { /* ignore */ }
|
|
2232
|
+
};
|
|
2233
|
+
/**
|
|
2234
|
+
* @private
|
|
2235
|
+
*/
|
|
2236
|
+
FormRenderer.coerceChecked = function (value) {
|
|
2237
|
+
if (typeof value === 'boolean') {
|
|
2238
|
+
return value;
|
|
2239
|
+
}
|
|
2240
|
+
if (typeof value === 'number') {
|
|
2241
|
+
return value !== 0;
|
|
2242
|
+
}
|
|
2243
|
+
if (typeof value === 'string') {
|
|
2244
|
+
return value !== '' && value !== 'false' && value !== '0';
|
|
2245
|
+
}
|
|
2246
|
+
return !!value;
|
|
2247
|
+
};
|
|
2248
|
+
/**
|
|
2156
2249
|
* @private
|
|
2157
2250
|
*/
|
|
2158
2251
|
FormRenderer.prototype.onPropertyChanged = function (newProps, oldProps) {
|
|
@@ -2160,6 +2253,9 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
2160
2253
|
if (newProps.schema !== oldProps.schema) {
|
|
2161
2254
|
reRender = true;
|
|
2162
2255
|
}
|
|
2256
|
+
if (newProps.dataModel !== oldProps.dataModel) {
|
|
2257
|
+
reRender = true;
|
|
2258
|
+
}
|
|
2163
2259
|
if (newProps.locale !== oldProps.locale) {
|
|
2164
2260
|
reRender = true;
|
|
2165
2261
|
}
|
|
@@ -2169,13 +2265,15 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
2169
2265
|
if (newProps.layout !== oldProps.layout) {
|
|
2170
2266
|
reRender = true;
|
|
2171
2267
|
}
|
|
2172
|
-
if (newProps.
|
|
2268
|
+
if (newProps.customWidgetSettings !== oldProps.customWidgetSettings) {
|
|
2173
2269
|
reRender = true;
|
|
2174
2270
|
}
|
|
2175
2271
|
if (!reRender) {
|
|
2176
2272
|
return;
|
|
2177
2273
|
}
|
|
2178
|
-
|
|
2274
|
+
if (this.isReact || this.isAngular) {
|
|
2275
|
+
this.clearTemplate();
|
|
2276
|
+
}
|
|
2179
2277
|
this.refreshing = true;
|
|
2180
2278
|
this.destroyRendered();
|
|
2181
2279
|
this.removePreviousRoot();
|
|
@@ -2184,7 +2282,6 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
2184
2282
|
this.refreshing = false;
|
|
2185
2283
|
};
|
|
2186
2284
|
/**
|
|
2187
|
-
* Destroy all child EJ2 instances, detach listeners, null refs.
|
|
2188
2285
|
* @private
|
|
2189
2286
|
*/
|
|
2190
2287
|
FormRenderer.prototype.destroyRendered = function () {
|
|
@@ -2217,7 +2314,6 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
2217
2314
|
this.pendingChangedFieldIds = new Set();
|
|
2218
2315
|
};
|
|
2219
2316
|
/**
|
|
2220
|
-
* Remove persisted tab selection state for this form when it is fully destroyed.
|
|
2221
2317
|
* @private
|
|
2222
2318
|
*/
|
|
2223
2319
|
FormRenderer.prototype.clearPersistedTabSelections = function () {
|
|
@@ -2237,11 +2333,43 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
2237
2333
|
catch (_a) {
|
|
2238
2334
|
}
|
|
2239
2335
|
};
|
|
2336
|
+
FormRenderer.prototype.getTemplateFunction = function (template) {
|
|
2337
|
+
var templateFn = null;
|
|
2338
|
+
try {
|
|
2339
|
+
if (typeof template === 'string' && template.indexOf('#') !== -1 && document.querySelectorAll(template).length) {
|
|
2340
|
+
templateFn = compile(this.sanitizeTemplateValue(document.querySelector(template).innerHTML.trim()));
|
|
2341
|
+
}
|
|
2342
|
+
else if (typeof template === 'string') {
|
|
2343
|
+
templateFn = compile(this.sanitizeTemplateValue(template));
|
|
2344
|
+
}
|
|
2345
|
+
else {
|
|
2346
|
+
templateFn = compile(template);
|
|
2347
|
+
}
|
|
2348
|
+
}
|
|
2349
|
+
catch (e) {
|
|
2350
|
+
templateFn = compile(template);
|
|
2351
|
+
}
|
|
2352
|
+
return templateFn;
|
|
2353
|
+
};
|
|
2354
|
+
/**
|
|
2355
|
+
* @private
|
|
2356
|
+
*/
|
|
2357
|
+
FormRenderer.prototype.sanitizeTemplateValue = function (value) {
|
|
2358
|
+
if (this.enableHtmlSanitizer && typeof value === 'string') {
|
|
2359
|
+
try {
|
|
2360
|
+
return SanitizeHtmlHelper.sanitize(value);
|
|
2361
|
+
}
|
|
2362
|
+
catch (e) { /* swallow */ }
|
|
2363
|
+
}
|
|
2364
|
+
return value;
|
|
2365
|
+
};
|
|
2240
2366
|
/**
|
|
2241
|
-
* Full component teardown.
|
|
2242
2367
|
* @private
|
|
2243
2368
|
*/
|
|
2244
2369
|
FormRenderer.prototype.destroy = function () {
|
|
2370
|
+
if (this.isReact || this.isAngular) {
|
|
2371
|
+
this.clearTemplate();
|
|
2372
|
+
}
|
|
2245
2373
|
this.destroyRendered();
|
|
2246
2374
|
this.formState = { values: {}, errors: {} };
|
|
2247
2375
|
this.expressionEngine = null;
|
|
@@ -2274,24 +2402,27 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
2274
2402
|
}
|
|
2275
2403
|
};
|
|
2276
2404
|
var FormRenderer_1;
|
|
2277
|
-
/**
|
|
2278
|
-
* Component types eligible for DOM preservation across re-renders.
|
|
2279
|
-
* These types either bind remote data (dataGrid, lookup-backed
|
|
2280
|
-
* dropdown/multiselect) or render many child options (checkboxGroup)
|
|
2281
|
-
* and are noticeably expensive / flicker-prone to rebuild.
|
|
2282
|
-
*/
|
|
2283
2405
|
FormRenderer.PRESERVABLE_TYPES = new Set([
|
|
2284
2406
|
'textbox', 'textarea', 'number', 'checkbox', 'checkboxGroup', 'radio', 'dropdown', 'multiselect', 'button', 'date', 'dateTime', 'time', 'dateRange', 'switch', 'signature', 'rating', 'imageEditor', 'fileUpload', 'rangeSlider', 'colorPicker', 'inputMask', 'message', 'panel', 'table', 'tabs', 'dataGrid', 'staticHtml', 'card', 'splitButton', 'richTextEditor'
|
|
2285
2407
|
]);
|
|
2286
2408
|
__decorate([
|
|
2287
2409
|
Property(null)
|
|
2288
2410
|
], FormRenderer.prototype, "schema", void 0);
|
|
2411
|
+
__decorate([
|
|
2412
|
+
Property(null)
|
|
2413
|
+
], FormRenderer.prototype, "dataModel", void 0);
|
|
2289
2414
|
__decorate([
|
|
2290
2415
|
Property('SingleColumn')
|
|
2291
2416
|
], FormRenderer.prototype, "layout", void 0);
|
|
2292
2417
|
__decorate([
|
|
2293
2418
|
Property('')
|
|
2294
2419
|
], FormRenderer.prototype, "className", void 0);
|
|
2420
|
+
__decorate([
|
|
2421
|
+
Collection([], CustomWidgetSetting)
|
|
2422
|
+
], FormRenderer.prototype, "customWidgetSettings", void 0);
|
|
2423
|
+
__decorate([
|
|
2424
|
+
Property(false)
|
|
2425
|
+
], FormRenderer.prototype, "enableHtmlSanitizer", void 0);
|
|
2295
2426
|
__decorate([
|
|
2296
2427
|
Event()
|
|
2297
2428
|
], FormRenderer.prototype, "submit", void 0);
|