@syncfusion/ej2-form-renderer 34.2.6 → 35.1.37
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/README.md +6 -3
- 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 +3261 -1523
- package/dist/es6/ej2-form-renderer.es2015.js.map +1 -1
- package/dist/es6/ej2-form-renderer.es5.js +3316 -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} +419 -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);
|
|
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' });
|
|
@@ -1369,6 +1401,9 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
1369
1401
|
return wrapper;
|
|
1370
1402
|
}
|
|
1371
1403
|
case 'splitButton': {
|
|
1404
|
+
if (resolveCustomWidget(component, this.customWidgetSettings)) {
|
|
1405
|
+
return this.renderField(component);
|
|
1406
|
+
}
|
|
1372
1407
|
var splitButtonDisabled = ConditionalRuleEngine.isFieldDisabled(component.conditions, formValues);
|
|
1373
1408
|
var computedDisabled = !!component.disabled || splitButtonDisabled;
|
|
1374
1409
|
var wrapper = createElement('div', { className: 'form-group' });
|
|
@@ -1422,11 +1457,6 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
1422
1457
|
this.beforeValidate(changedFieldId);
|
|
1423
1458
|
this.validator.validate(changedFieldId);
|
|
1424
1459
|
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
1460
|
if (changedFieldId && this.isConditionalTrigger(changedFieldId)) {
|
|
1431
1461
|
this.scheduleRerender(changedFieldId);
|
|
1432
1462
|
}
|
|
@@ -1440,6 +1470,9 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
1440
1470
|
infoElement.classList.remove('e-error');
|
|
1441
1471
|
}
|
|
1442
1472
|
var inputElement = this.getInputElementByName(fieldId);
|
|
1473
|
+
if (!inputElement) {
|
|
1474
|
+
return;
|
|
1475
|
+
}
|
|
1443
1476
|
var inputParent = inputElement.parentElement;
|
|
1444
1477
|
var grandParent = inputParent.parentElement;
|
|
1445
1478
|
if (inputParent.classList.contains('e-control-wrapper') || inputParent.classList.contains('e-wrapper') ||
|
|
@@ -1474,23 +1507,15 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
1474
1507
|
};
|
|
1475
1508
|
/**
|
|
1476
1509
|
* @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
1510
|
*/
|
|
1484
1511
|
FormRenderer.prototype.collectConditionFieldIds = function (condition, acc) {
|
|
1485
1512
|
if (!condition) {
|
|
1486
1513
|
return;
|
|
1487
1514
|
}
|
|
1488
1515
|
if (typeof condition.field === 'string') {
|
|
1489
|
-
// Leaf rule.
|
|
1490
1516
|
acc.add(condition.field);
|
|
1491
1517
|
}
|
|
1492
1518
|
else if (Array.isArray(condition.rules)) {
|
|
1493
|
-
// Composite (and/or) — recurse.
|
|
1494
1519
|
for (var _i = 0, _a = condition.rules; _i < _a.length; _i++) {
|
|
1495
1520
|
var sub = _a[_i];
|
|
1496
1521
|
this.collectConditionFieldIds(sub, acc);
|
|
@@ -1519,18 +1544,9 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
1519
1544
|
};
|
|
1520
1545
|
/**
|
|
1521
1546
|
* @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
1547
|
*/
|
|
1531
1548
|
FormRenderer.prototype.buildConditionalDependencyMap = function () {
|
|
1532
1549
|
var triggers = new Set();
|
|
1533
|
-
// Per-consumer dependency set (rebuilt each pass).
|
|
1534
1550
|
var consumerDeps = new Map();
|
|
1535
1551
|
var allComps = this.collectAllComponents(this.processedSchemaCache.components);
|
|
1536
1552
|
var _loop_3 = function (comp) {
|
|
@@ -1561,7 +1577,6 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
1561
1577
|
this_1.collectConditionFieldIds(item.condition, triggers);
|
|
1562
1578
|
this_1.collectConditionFieldIds(item.condition, myDeps);
|
|
1563
1579
|
}
|
|
1564
|
-
// DataGrid conditional columns
|
|
1565
1580
|
if (item && Array.isArray(item.conditions)) {
|
|
1566
1581
|
for (var _c = 0, _d = item.conditions; _c < _d.length; _c++) {
|
|
1567
1582
|
var subCond = _d[_c];
|
|
@@ -1609,13 +1624,6 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
1609
1624
|
collectMinMaxReferenceIds(range);
|
|
1610
1625
|
}
|
|
1611
1626
|
}
|
|
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
1627
|
var ds = comp.dataSource;
|
|
1620
1628
|
if ((comp.type === 'dataGrid') &&
|
|
1621
1629
|
ds &&
|
|
@@ -1645,26 +1653,29 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
1645
1653
|
};
|
|
1646
1654
|
/**
|
|
1647
1655
|
* @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
1656
|
*/
|
|
1657
1657
|
FormRenderer.prototype.isConditionalTrigger = function (fieldId) {
|
|
1658
1658
|
return this.conditionalTriggerFieldIds.has(fieldId);
|
|
1659
1659
|
};
|
|
1660
|
+
FormRenderer.prototype.getScrollParent = function () {
|
|
1661
|
+
var parent = this.element.parentElement;
|
|
1662
|
+
while (parent) {
|
|
1663
|
+
var style = window.getComputedStyle(parent);
|
|
1664
|
+
var overflowY = style.overflowY;
|
|
1665
|
+
var overflowX = style.overflowX;
|
|
1666
|
+
var canScrollY = (overflowY === 'auto' || overflowY === 'scroll' || overflowY === 'overlay') &&
|
|
1667
|
+
parent.scrollHeight > parent.clientHeight;
|
|
1668
|
+
var canScrollX = (overflowX === 'auto' || overflowX === 'scroll' || overflowX === 'overlay') &&
|
|
1669
|
+
parent.scrollWidth > parent.clientWidth;
|
|
1670
|
+
if (canScrollY || canScrollX) {
|
|
1671
|
+
return parent;
|
|
1672
|
+
}
|
|
1673
|
+
parent = parent.parentElement;
|
|
1674
|
+
}
|
|
1675
|
+
return null;
|
|
1676
|
+
};
|
|
1660
1677
|
/**
|
|
1661
1678
|
* @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
1679
|
*/
|
|
1669
1680
|
FormRenderer.prototype.rerenderForm = function (changedFieldIds) {
|
|
1670
1681
|
var _this = this;
|
|
@@ -1680,12 +1691,15 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
1680
1691
|
selectionStart = activeEl.selectionStart;
|
|
1681
1692
|
selectionEnd = activeEl.selectionEnd;
|
|
1682
1693
|
}
|
|
1683
|
-
catch (e) { /*
|
|
1694
|
+
catch (e) { /* ignore */ }
|
|
1684
1695
|
}
|
|
1685
1696
|
var savedElementScrollTop = this.element.scrollTop;
|
|
1686
1697
|
var savedElementScrollLeft = this.element.scrollLeft;
|
|
1687
1698
|
var savedWindowScrollX = window.scrollX;
|
|
1688
1699
|
var savedWindowScrollY = window.scrollY;
|
|
1700
|
+
var scrollParent = this.getScrollParent();
|
|
1701
|
+
var savedScrollParentTop = scrollParent ? scrollParent.scrollTop : 0;
|
|
1702
|
+
var savedScrollParentLeft = scrollParent ? scrollParent.scrollLeft : 0;
|
|
1689
1703
|
this.preservedFields.clear();
|
|
1690
1704
|
var allComps = this.collectAllComponents(this.processedSchemaCache.components);
|
|
1691
1705
|
var _loop_4 = function (comp) {
|
|
@@ -1716,6 +1730,9 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
1716
1730
|
_loop_4(comp);
|
|
1717
1731
|
}
|
|
1718
1732
|
this.refreshing = true;
|
|
1733
|
+
if (this.isReact || this.isAngular) {
|
|
1734
|
+
this.clearTemplate();
|
|
1735
|
+
}
|
|
1719
1736
|
this.destroyRenderedExcludingPreserved();
|
|
1720
1737
|
this.removePreviousRoot();
|
|
1721
1738
|
if (this.validator) {
|
|
@@ -1726,6 +1743,10 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
1726
1743
|
try {
|
|
1727
1744
|
this.element.scrollTop = savedElementScrollTop;
|
|
1728
1745
|
this.element.scrollLeft = savedElementScrollLeft;
|
|
1746
|
+
if (scrollParent) {
|
|
1747
|
+
scrollParent.scrollTop = savedScrollParentTop;
|
|
1748
|
+
scrollParent.scrollLeft = savedScrollParentLeft;
|
|
1749
|
+
}
|
|
1729
1750
|
window.scrollTo(savedWindowScrollX, savedWindowScrollY);
|
|
1730
1751
|
}
|
|
1731
1752
|
catch (e) { /* swallow */ }
|
|
@@ -1745,15 +1766,9 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
1745
1766
|
catch (e) { /* swallow */ }
|
|
1746
1767
|
}
|
|
1747
1768
|
}
|
|
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
1769
|
if (this.preservedFields.size > 0) {
|
|
1752
1770
|
var stillKept_1 = [];
|
|
1753
1771
|
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
1772
|
if (!_this.element.contains(node) && !document.body.contains(node)) {
|
|
1758
1773
|
_this.destroyPreservedSubtree(node);
|
|
1759
1774
|
try {
|
|
@@ -1762,7 +1777,7 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
1762
1777
|
}
|
|
1763
1778
|
}
|
|
1764
1779
|
catch (e) {
|
|
1765
|
-
//
|
|
1780
|
+
// ignore
|
|
1766
1781
|
}
|
|
1767
1782
|
_this.preservedFields.delete(id);
|
|
1768
1783
|
}
|
|
@@ -1816,11 +1831,6 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
1816
1831
|
};
|
|
1817
1832
|
/**
|
|
1818
1833
|
* @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
1834
|
*/
|
|
1825
1835
|
FormRenderer.prototype.destroyRenderedExcludingPreserved = function () {
|
|
1826
1836
|
var survived = [];
|
|
@@ -1841,8 +1851,6 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
1841
1851
|
_loop_5(inst);
|
|
1842
1852
|
}
|
|
1843
1853
|
this.renderedInstances = survived;
|
|
1844
|
-
// Prune inputRefs whose host element lives in a destroyed subtree
|
|
1845
|
-
// (preserved ones stay).
|
|
1846
1854
|
var inputRefKeys = Object.keys(this.inputRefs);
|
|
1847
1855
|
var _loop_6 = function (key) {
|
|
1848
1856
|
var inst = this_4.inputRefs[key];
|
|
@@ -1865,10 +1873,6 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
1865
1873
|
};
|
|
1866
1874
|
/**
|
|
1867
1875
|
* @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
1876
|
*/
|
|
1873
1877
|
FormRenderer.prototype.destroyPreservedSubtree = function (rootNode) {
|
|
1874
1878
|
var survived = [];
|
|
@@ -1898,7 +1902,6 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
1898
1902
|
return inputEl;
|
|
1899
1903
|
};
|
|
1900
1904
|
/**
|
|
1901
|
-
* Evaluate expressions in topological order with type coercion.
|
|
1902
1905
|
* @private
|
|
1903
1906
|
*/
|
|
1904
1907
|
FormRenderer.prototype.evaluateExpressions = function () {
|
|
@@ -1999,22 +2002,10 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
1999
2002
|
}
|
|
2000
2003
|
if (result !== null && result !== undefined && result !== formValues[component.id] && this_5.formState) {
|
|
2001
2004
|
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
2005
|
if (this_5.validator) {
|
|
2006
2006
|
var inputEl = this_5.getInputElementByName(component.id);
|
|
2007
2007
|
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 */ }
|
|
2008
|
+
this_5.syncValueToInput(inputEl, component.id, result);
|
|
2018
2009
|
}
|
|
2019
2010
|
}
|
|
2020
2011
|
}
|
|
@@ -2041,7 +2032,6 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
2041
2032
|
}
|
|
2042
2033
|
};
|
|
2043
2034
|
/**
|
|
2044
|
-
* Re-trigger custom validation for changed + dependent fields.
|
|
2045
2035
|
* @private
|
|
2046
2036
|
*/
|
|
2047
2037
|
FormRenderer.prototype.retriggerCustomValidation = function () {
|
|
@@ -2146,13 +2136,106 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
2146
2136
|
}
|
|
2147
2137
|
};
|
|
2148
2138
|
/**
|
|
2149
|
-
* Retrieves the underlying Syncfusion form-input component instance by its field name.
|
|
2139
|
+
* Retrieves the underlying Syncfusion form-input component instance by its field name.
|
|
2140
|
+
* Use this to call Syncfusion component methods and properties.
|
|
2141
|
+
*
|
|
2142
|
+
* @param {string} name - Specifies the name for the built-in Syncfusion component.
|
|
2143
|
+
* @returns {object | null} - Specifies the instance of the Syncfusion component in the form.
|
|
2150
2144
|
*/
|
|
2151
2145
|
FormRenderer.prototype.getComponent = function (name) {
|
|
2152
2146
|
return this.inputRefs[name] || null;
|
|
2153
2147
|
};
|
|
2154
2148
|
/**
|
|
2155
|
-
*
|
|
2149
|
+
* Programmatically sets a form field's value for user edits.
|
|
2150
|
+
*
|
|
2151
|
+
* @param {string} fieldName - The field's `name` (the schema property's `name`).
|
|
2152
|
+
* @param {any} value - The new value to set.
|
|
2153
|
+
* @returns void
|
|
2154
|
+
*/
|
|
2155
|
+
FormRenderer.prototype.setFieldValue = function (fieldName, value) {
|
|
2156
|
+
var allComponents = this.collectAllComponents(this.processedSchemaCache.components || []);
|
|
2157
|
+
var component = allComponents.find(function (c) { return c.name === fieldName; });
|
|
2158
|
+
if (!component) {
|
|
2159
|
+
return;
|
|
2160
|
+
}
|
|
2161
|
+
if (this.formState) {
|
|
2162
|
+
this.formState.values[component.id] = value;
|
|
2163
|
+
}
|
|
2164
|
+
var inputEl = this.getInputElementByName(component.id);
|
|
2165
|
+
if (inputEl) {
|
|
2166
|
+
this.syncValueToInput(inputEl, component.id, value);
|
|
2167
|
+
}
|
|
2168
|
+
this.afterValueChange(component.id);
|
|
2169
|
+
};
|
|
2170
|
+
/**
|
|
2171
|
+
* @private
|
|
2172
|
+
*/
|
|
2173
|
+
FormRenderer.prototype.syncValueToInput = function (inputEl, fieldId, value) {
|
|
2174
|
+
if (!inputEl) {
|
|
2175
|
+
return;
|
|
2176
|
+
}
|
|
2177
|
+
try {
|
|
2178
|
+
var nativeInput = (inputEl instanceof HTMLInputElement) ? inputEl : null;
|
|
2179
|
+
var isCheckable = !!nativeInput &&
|
|
2180
|
+
(nativeInput.type === 'checkbox' || nativeInput.type === 'radio');
|
|
2181
|
+
var ej2Inst = inputEl.ej2_instances && inputEl.ej2_instances[0];
|
|
2182
|
+
if (ej2Inst) {
|
|
2183
|
+
if (isCheckable && typeof ej2Inst.checked !== 'undefined') {
|
|
2184
|
+
if (nativeInput.type === 'radio' && typeof ej2Inst.value !== 'undefined') {
|
|
2185
|
+
ej2Inst.checked = String(value) === String(ej2Inst.value);
|
|
2186
|
+
}
|
|
2187
|
+
else {
|
|
2188
|
+
ej2Inst.checked = FormRenderer_1.coerceChecked(value);
|
|
2189
|
+
}
|
|
2190
|
+
}
|
|
2191
|
+
else if (typeof ej2Inst.value !== 'undefined') {
|
|
2192
|
+
ej2Inst.value = value;
|
|
2193
|
+
}
|
|
2194
|
+
return;
|
|
2195
|
+
}
|
|
2196
|
+
if (inputEl instanceof HTMLSelectElement) {
|
|
2197
|
+
var strValue = (value === null || value === undefined) ? '' : String(value);
|
|
2198
|
+
inputEl.value = strValue;
|
|
2199
|
+
if (inputEl.value !== strValue && inputEl.options.length > 0) {
|
|
2200
|
+
for (var i = 0; i < inputEl.options.length; i++) {
|
|
2201
|
+
if (inputEl.options[i].text === strValue) {
|
|
2202
|
+
inputEl.value = inputEl.options[i].value;
|
|
2203
|
+
break;
|
|
2204
|
+
}
|
|
2205
|
+
}
|
|
2206
|
+
}
|
|
2207
|
+
}
|
|
2208
|
+
else if (nativeInput && nativeInput.type === 'radio') {
|
|
2209
|
+
var radios = this.element.querySelectorAll("input[type=\"radio\"][name=\"" + fieldId + "\"]");
|
|
2210
|
+
for (var i = 0; i < radios.length; i++) {
|
|
2211
|
+
radios[i].checked = String(value) === radios[i].value;
|
|
2212
|
+
}
|
|
2213
|
+
}
|
|
2214
|
+
else if (isCheckable) {
|
|
2215
|
+
nativeInput.checked = FormRenderer_1.coerceChecked(value);
|
|
2216
|
+
}
|
|
2217
|
+
else if (typeof inputEl.value !== 'undefined') {
|
|
2218
|
+
inputEl.value = (value === null || value === undefined) ? '' : String(value);
|
|
2219
|
+
}
|
|
2220
|
+
}
|
|
2221
|
+
catch (e) { /* ignore */ }
|
|
2222
|
+
};
|
|
2223
|
+
/**
|
|
2224
|
+
* @private
|
|
2225
|
+
*/
|
|
2226
|
+
FormRenderer.coerceChecked = function (value) {
|
|
2227
|
+
if (typeof value === 'boolean') {
|
|
2228
|
+
return value;
|
|
2229
|
+
}
|
|
2230
|
+
if (typeof value === 'number') {
|
|
2231
|
+
return value !== 0;
|
|
2232
|
+
}
|
|
2233
|
+
if (typeof value === 'string') {
|
|
2234
|
+
return value !== '' && value !== 'false' && value !== '0';
|
|
2235
|
+
}
|
|
2236
|
+
return !!value;
|
|
2237
|
+
};
|
|
2238
|
+
/**
|
|
2156
2239
|
* @private
|
|
2157
2240
|
*/
|
|
2158
2241
|
FormRenderer.prototype.onPropertyChanged = function (newProps, oldProps) {
|
|
@@ -2160,6 +2243,9 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
2160
2243
|
if (newProps.schema !== oldProps.schema) {
|
|
2161
2244
|
reRender = true;
|
|
2162
2245
|
}
|
|
2246
|
+
if (newProps.dataModel !== oldProps.dataModel) {
|
|
2247
|
+
reRender = true;
|
|
2248
|
+
}
|
|
2163
2249
|
if (newProps.locale !== oldProps.locale) {
|
|
2164
2250
|
reRender = true;
|
|
2165
2251
|
}
|
|
@@ -2169,13 +2255,15 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
2169
2255
|
if (newProps.layout !== oldProps.layout) {
|
|
2170
2256
|
reRender = true;
|
|
2171
2257
|
}
|
|
2172
|
-
if (newProps.
|
|
2258
|
+
if (newProps.customWidgetSettings !== oldProps.customWidgetSettings) {
|
|
2173
2259
|
reRender = true;
|
|
2174
2260
|
}
|
|
2175
2261
|
if (!reRender) {
|
|
2176
2262
|
return;
|
|
2177
2263
|
}
|
|
2178
|
-
|
|
2264
|
+
if (this.isReact || this.isAngular) {
|
|
2265
|
+
this.clearTemplate();
|
|
2266
|
+
}
|
|
2179
2267
|
this.refreshing = true;
|
|
2180
2268
|
this.destroyRendered();
|
|
2181
2269
|
this.removePreviousRoot();
|
|
@@ -2184,7 +2272,6 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
2184
2272
|
this.refreshing = false;
|
|
2185
2273
|
};
|
|
2186
2274
|
/**
|
|
2187
|
-
* Destroy all child EJ2 instances, detach listeners, null refs.
|
|
2188
2275
|
* @private
|
|
2189
2276
|
*/
|
|
2190
2277
|
FormRenderer.prototype.destroyRendered = function () {
|
|
@@ -2217,7 +2304,6 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
2217
2304
|
this.pendingChangedFieldIds = new Set();
|
|
2218
2305
|
};
|
|
2219
2306
|
/**
|
|
2220
|
-
* Remove persisted tab selection state for this form when it is fully destroyed.
|
|
2221
2307
|
* @private
|
|
2222
2308
|
*/
|
|
2223
2309
|
FormRenderer.prototype.clearPersistedTabSelections = function () {
|
|
@@ -2237,11 +2323,43 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
2237
2323
|
catch (_a) {
|
|
2238
2324
|
}
|
|
2239
2325
|
};
|
|
2326
|
+
FormRenderer.prototype.getTemplateFunction = function (template) {
|
|
2327
|
+
var templateFn = null;
|
|
2328
|
+
try {
|
|
2329
|
+
if (typeof template === 'string' && template.indexOf('#') !== -1 && document.querySelectorAll(template).length) {
|
|
2330
|
+
templateFn = compile(this.sanitizeTemplateValue(document.querySelector(template).innerHTML.trim()));
|
|
2331
|
+
}
|
|
2332
|
+
else if (typeof template === 'string') {
|
|
2333
|
+
templateFn = compile(this.sanitizeTemplateValue(template));
|
|
2334
|
+
}
|
|
2335
|
+
else {
|
|
2336
|
+
templateFn = compile(template);
|
|
2337
|
+
}
|
|
2338
|
+
}
|
|
2339
|
+
catch (e) {
|
|
2340
|
+
templateFn = compile(template);
|
|
2341
|
+
}
|
|
2342
|
+
return templateFn;
|
|
2343
|
+
};
|
|
2344
|
+
/**
|
|
2345
|
+
* @private
|
|
2346
|
+
*/
|
|
2347
|
+
FormRenderer.prototype.sanitizeTemplateValue = function (value) {
|
|
2348
|
+
if (this.enableHtmlSanitizer && typeof value === 'string') {
|
|
2349
|
+
try {
|
|
2350
|
+
return SanitizeHtmlHelper.sanitize(value);
|
|
2351
|
+
}
|
|
2352
|
+
catch (e) { /* swallow */ }
|
|
2353
|
+
}
|
|
2354
|
+
return value;
|
|
2355
|
+
};
|
|
2240
2356
|
/**
|
|
2241
|
-
* Full component teardown.
|
|
2242
2357
|
* @private
|
|
2243
2358
|
*/
|
|
2244
2359
|
FormRenderer.prototype.destroy = function () {
|
|
2360
|
+
if (this.isReact || this.isAngular) {
|
|
2361
|
+
this.clearTemplate();
|
|
2362
|
+
}
|
|
2245
2363
|
this.destroyRendered();
|
|
2246
2364
|
this.formState = { values: {}, errors: {} };
|
|
2247
2365
|
this.expressionEngine = null;
|
|
@@ -2274,24 +2392,27 @@ var FormRenderer = /** @class */ (function (_super) {
|
|
|
2274
2392
|
}
|
|
2275
2393
|
};
|
|
2276
2394
|
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
2395
|
FormRenderer.PRESERVABLE_TYPES = new Set([
|
|
2284
2396
|
'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
2397
|
]);
|
|
2286
2398
|
__decorate([
|
|
2287
2399
|
Property(null)
|
|
2288
2400
|
], FormRenderer.prototype, "schema", void 0);
|
|
2401
|
+
__decorate([
|
|
2402
|
+
Property(null)
|
|
2403
|
+
], FormRenderer.prototype, "dataModel", void 0);
|
|
2289
2404
|
__decorate([
|
|
2290
2405
|
Property('SingleColumn')
|
|
2291
2406
|
], FormRenderer.prototype, "layout", void 0);
|
|
2292
2407
|
__decorate([
|
|
2293
2408
|
Property('')
|
|
2294
2409
|
], FormRenderer.prototype, "className", void 0);
|
|
2410
|
+
__decorate([
|
|
2411
|
+
Collection([], CustomWidgetSetting)
|
|
2412
|
+
], FormRenderer.prototype, "customWidgetSettings", void 0);
|
|
2413
|
+
__decorate([
|
|
2414
|
+
Property(false)
|
|
2415
|
+
], FormRenderer.prototype, "enableHtmlSanitizer", void 0);
|
|
2295
2416
|
__decorate([
|
|
2296
2417
|
Event()
|
|
2297
2418
|
], FormRenderer.prototype, "submit", void 0);
|