@syncfusion/ej2-form-renderer 34.2.2
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 +60 -0
- package/common.d.ts +4 -0
- package/common.js +4 -0
- package/dist/ej2-form-renderer.umd.min.js +11 -0
- package/dist/ej2-form-renderer.umd.min.js.map +1 -0
- package/dist/es6/ej2-form-renderer.es2015.js +6787 -0
- package/dist/es6/ej2-form-renderer.es2015.js.map +1 -0
- package/dist/es6/ej2-form-renderer.es5.js +7055 -0
- package/dist/es6/ej2-form-renderer.es5.js.map +1 -0
- package/dist/global/ej2-form-renderer.min.js +11 -0
- package/dist/global/ej2-form-renderer.min.js.map +1 -0
- package/dist/global/index.d.ts +14 -0
- package/form-renderer.d.ts +4 -0
- package/form-renderer.js +4 -0
- package/index.d.ts +4 -0
- package/index.js +4 -0
- package/license +10 -0
- package/package.json +41 -0
- package/src/common/checkbox-group.d.ts +55 -0
- package/src/common/checkbox-group.js +241 -0
- package/src/common/conditional-rule-engine.d.ts +241 -0
- package/src/common/conditional-rule-engine.js +505 -0
- package/src/common/custom-validation-engine.d.ts +57 -0
- package/src/common/custom-validation-engine.js +152 -0
- package/src/common/datagrid-component.d.ts +156 -0
- package/src/common/datagrid-component.js +410 -0
- package/src/common/expressions/dependency-tracker.d.ts +29 -0
- package/src/common/expressions/dependency-tracker.js +137 -0
- package/src/common/expressions/expression-engine.d.ts +94 -0
- package/src/common/expressions/expression-engine.js +514 -0
- package/src/common/expressions/expression-parser.d.ts +40 -0
- package/src/common/expressions/expression-parser.js +270 -0
- package/src/common/expressions/grid-expressions.d.ts +24 -0
- package/src/common/expressions/grid-expressions.js +92 -0
- package/src/common/expressions/index.d.ts +4 -0
- package/src/common/expressions/index.js +4 -0
- package/src/common/index.d.ts +10 -0
- package/src/common/index.js +10 -0
- package/src/common/json-converter.d.ts +945 -0
- package/src/common/json-converter.js +1110 -0
- package/src/common/minmax-rule-engine.d.ts +105 -0
- package/src/common/minmax-rule-engine.js +380 -0
- package/src/common/option-fetcher.d.ts +30 -0
- package/src/common/option-fetcher.js +139 -0
- package/src/common/parser.d.ts +98 -0
- package/src/common/parser.js +788 -0
- package/src/common/static-html-renderer.d.ts +45 -0
- package/src/common/static-html-renderer.js +77 -0
- package/src/common/utils.d.ts +116 -0
- package/src/common/utils.js +484 -0
- package/src/form-renderer/form-renderer-model.d.ts +65 -0
- package/src/form-renderer/form-renderer.d.ts +425 -0
- package/src/form-renderer/form-renderer.js +2277 -0
- package/src/form-renderer/index.d.ts +6 -0
- package/src/form-renderer/index.js +5 -0
- package/src/form-renderer/render-form-field.d.ts +31 -0
- package/src/form-renderer/render-form-field.js +816 -0
- package/src/form-renderer/types/form-schema.d.ts +452 -0
- package/src/form-renderer/types/form-schema.js +32 -0
- package/src/global.js +1 -0
- package/src/index.d.ts +4 -0
- package/src/index.js +4 -0
- package/styles/bds-lite.css +599 -0
- package/styles/bds-lite.scss +2 -0
- package/styles/bds.css +599 -0
- package/styles/bds.scss +2 -0
- package/styles/bootstrap-dark-lite.css +608 -0
- package/styles/bootstrap-dark-lite.scss +2 -0
- package/styles/bootstrap-dark.css +608 -0
- package/styles/bootstrap-dark.scss +2 -0
- package/styles/bootstrap-lite.css +595 -0
- package/styles/bootstrap-lite.scss +2 -0
- package/styles/bootstrap.css +595 -0
- package/styles/bootstrap.scss +2 -0
- package/styles/bootstrap4-lite.css +595 -0
- package/styles/bootstrap4-lite.scss +2 -0
- package/styles/bootstrap4.css +595 -0
- package/styles/bootstrap4.scss +2 -0
- package/styles/bootstrap5-dark-lite.css +595 -0
- package/styles/bootstrap5-dark-lite.scss +2 -0
- package/styles/bootstrap5-dark.css +595 -0
- package/styles/bootstrap5-dark.scss +2 -0
- package/styles/bootstrap5-lite.css +595 -0
- package/styles/bootstrap5-lite.scss +2 -0
- package/styles/bootstrap5.3-lite.css +679 -0
- package/styles/bootstrap5.3-lite.scss +2 -0
- package/styles/bootstrap5.3.css +679 -0
- package/styles/bootstrap5.3.scss +2 -0
- package/styles/bootstrap5.css +595 -0
- package/styles/bootstrap5.scss +2 -0
- package/styles/fabric-dark-lite.css +608 -0
- package/styles/fabric-dark-lite.scss +2 -0
- package/styles/fabric-dark.css +608 -0
- package/styles/fabric-dark.scss +2 -0
- package/styles/fabric-lite.css +595 -0
- package/styles/fabric-lite.scss +2 -0
- package/styles/fabric.css +595 -0
- package/styles/fabric.scss +2 -0
- package/styles/fluent-dark-lite.css +595 -0
- package/styles/fluent-dark-lite.scss +2 -0
- package/styles/fluent-dark.css +595 -0
- package/styles/fluent-dark.scss +2 -0
- package/styles/fluent-lite.css +595 -0
- package/styles/fluent-lite.scss +2 -0
- package/styles/fluent.css +595 -0
- package/styles/fluent.scss +2 -0
- package/styles/fluent2-lite.css +681 -0
- package/styles/fluent2-lite.scss +2 -0
- package/styles/fluent2.css +681 -0
- package/styles/fluent2.scss +2 -0
- package/styles/form-renderer/_all.scss +2 -0
- package/styles/form-renderer/_bds-definition.scss +8 -0
- package/styles/form-renderer/_bootstrap-dark-definition.scss +8 -0
- package/styles/form-renderer/_bootstrap-definition.scss +8 -0
- package/styles/form-renderer/_bootstrap4-definition.scss +8 -0
- package/styles/form-renderer/_bootstrap5-dark-definition.scss +8 -0
- package/styles/form-renderer/_bootstrap5-definition.scss +8 -0
- package/styles/form-renderer/_bootstrap5.3-definition.scss +8 -0
- package/styles/form-renderer/_fabric-dark-definition.scss +8 -0
- package/styles/form-renderer/_fabric-definition.scss +8 -0
- package/styles/form-renderer/_fluent-dark-definition.scss +8 -0
- package/styles/form-renderer/_fluent-definition.scss +8 -0
- package/styles/form-renderer/_fluent2-definition.scss +8 -0
- package/styles/form-renderer/_highcontrast-definition.scss +8 -0
- package/styles/form-renderer/_highcontrast-light-definition.scss +8 -0
- package/styles/form-renderer/_layout.scss +480 -0
- package/styles/form-renderer/_material-dark-definition.scss +8 -0
- package/styles/form-renderer/_material-definition.scss +8 -0
- package/styles/form-renderer/_material3-dark-definition.scss +8 -0
- package/styles/form-renderer/_material3-definition.scss +8 -0
- package/styles/form-renderer/_mixin.scss +26 -0
- package/styles/form-renderer/_tailwind-dark-definition.scss +8 -0
- package/styles/form-renderer/_tailwind-definition.scss +8 -0
- package/styles/form-renderer/_tailwind3-definition.scss +8 -0
- package/styles/form-renderer/_theme.scss +69 -0
- package/styles/form-renderer/_variables.scss +2 -0
- package/styles/form-renderer/bds.css +599 -0
- package/styles/form-renderer/bds.scss +2 -0
- package/styles/form-renderer/bootstrap-dark.css +608 -0
- package/styles/form-renderer/bootstrap-dark.scss +2 -0
- package/styles/form-renderer/bootstrap.css +595 -0
- package/styles/form-renderer/bootstrap.scss +2 -0
- package/styles/form-renderer/bootstrap4.css +595 -0
- package/styles/form-renderer/bootstrap4.scss +2 -0
- package/styles/form-renderer/bootstrap5-dark.css +595 -0
- package/styles/form-renderer/bootstrap5-dark.scss +2 -0
- package/styles/form-renderer/bootstrap5.3.css +679 -0
- package/styles/form-renderer/bootstrap5.3.scss +2 -0
- package/styles/form-renderer/bootstrap5.css +595 -0
- package/styles/form-renderer/bootstrap5.scss +2 -0
- package/styles/form-renderer/fabric-dark.css +608 -0
- package/styles/form-renderer/fabric-dark.scss +2 -0
- package/styles/form-renderer/fabric.css +595 -0
- package/styles/form-renderer/fabric.scss +2 -0
- package/styles/form-renderer/fluent-dark.css +595 -0
- package/styles/form-renderer/fluent-dark.scss +2 -0
- package/styles/form-renderer/fluent.css +595 -0
- package/styles/form-renderer/fluent.scss +2 -0
- package/styles/form-renderer/fluent2.css +681 -0
- package/styles/form-renderer/fluent2.scss +2 -0
- package/styles/form-renderer/highcontrast-light.css +595 -0
- package/styles/form-renderer/highcontrast-light.scss +2 -0
- package/styles/form-renderer/highcontrast.css +608 -0
- package/styles/form-renderer/highcontrast.scss +2 -0
- package/styles/form-renderer/material-dark.css +608 -0
- package/styles/form-renderer/material-dark.scss +2 -0
- package/styles/form-renderer/material.css +595 -0
- package/styles/form-renderer/material.scss +2 -0
- package/styles/form-renderer/material3-dark.css +677 -0
- package/styles/form-renderer/material3-dark.scss +2 -0
- package/styles/form-renderer/material3.css +679 -0
- package/styles/form-renderer/material3.scss +2 -0
- package/styles/form-renderer/tailwind-dark.css +595 -0
- package/styles/form-renderer/tailwind-dark.scss +2 -0
- package/styles/form-renderer/tailwind.css +595 -0
- package/styles/form-renderer/tailwind.scss +2 -0
- package/styles/form-renderer/tailwind3.css +669 -0
- package/styles/form-renderer/tailwind3.scss +2 -0
- package/styles/highcontrast-light-lite.css +595 -0
- package/styles/highcontrast-light-lite.scss +2 -0
- package/styles/highcontrast-light.css +595 -0
- package/styles/highcontrast-light.scss +2 -0
- package/styles/highcontrast-lite.css +608 -0
- package/styles/highcontrast-lite.scss +2 -0
- package/styles/highcontrast.css +608 -0
- package/styles/highcontrast.scss +2 -0
- package/styles/material-dark-lite.css +608 -0
- package/styles/material-dark-lite.scss +2 -0
- package/styles/material-dark.css +608 -0
- package/styles/material-dark.scss +2 -0
- package/styles/material-lite.css +595 -0
- package/styles/material-lite.scss +2 -0
- package/styles/material.css +595 -0
- package/styles/material.scss +2 -0
- package/styles/material3-dark-lite.css +677 -0
- package/styles/material3-dark-lite.scss +2 -0
- package/styles/material3-dark.css +677 -0
- package/styles/material3-dark.scss +2 -0
- package/styles/material3-lite.css +679 -0
- package/styles/material3-lite.scss +2 -0
- package/styles/material3.css +679 -0
- package/styles/material3.scss +2 -0
- package/styles/tailwind-dark-lite.css +595 -0
- package/styles/tailwind-dark-lite.scss +2 -0
- package/styles/tailwind-dark.css +595 -0
- package/styles/tailwind-dark.scss +2 -0
- package/styles/tailwind-lite.css +595 -0
- package/styles/tailwind-lite.scss +2 -0
- package/styles/tailwind.css +595 -0
- package/styles/tailwind.scss +2 -0
- package/styles/tailwind3-lite.css +669 -0
- package/styles/tailwind3-lite.scss +2 -0
- package/styles/tailwind3.css +669 -0
- package/styles/tailwind3.scss +2 -0
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
var __assign = (this && this.__assign) || function () {
|
|
2
|
+
__assign = Object.assign || function(t) {
|
|
3
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
4
|
+
s = arguments[i];
|
|
5
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
6
|
+
t[p] = s[p];
|
|
7
|
+
}
|
|
8
|
+
return t;
|
|
9
|
+
};
|
|
10
|
+
return __assign.apply(this, arguments);
|
|
11
|
+
};
|
|
12
|
+
import { Grid, Edit, Toolbar, Page, Resize, Sort, Filter } from '@syncfusion/ej2-grids';
|
|
13
|
+
import { GridExpressions } from './expressions/grid-expressions';
|
|
14
|
+
import { CustomValidationEngine } from './custom-validation-engine';
|
|
15
|
+
/**
|
|
16
|
+
* @private
|
|
17
|
+
*
|
|
18
|
+
* `DataGridComponent` is the Category C native reimplementation of
|
|
19
|
+
* `Common/DataGridComponent.tsx` using the EJ2 `Grid` (with `Edit`,
|
|
20
|
+
* `Toolbar`, `Page`, `Resize`, `Sort`, `Filter` inject modules).
|
|
21
|
+
*
|
|
22
|
+
* Reproduces:
|
|
23
|
+
* - internal current-data state seeded from `dataSource`;
|
|
24
|
+
* - calculated/expression columns (disable `allowEditing`, recompute on
|
|
25
|
+
* sibling field change via edit `change` params, update UI value by
|
|
26
|
+
* column type);
|
|
27
|
+
* - per-column custom validation merged into `validationRules`
|
|
28
|
+
* (required + custom validator via `CustomValidationEngine`);
|
|
29
|
+
* - dynamic toolbar (`Add`/`Edit`/`Delete` conditional + always
|
|
30
|
+
* `Update`/`Cancel`);
|
|
31
|
+
* - `actionComplete` → sync state + `onDataChange` callback;
|
|
32
|
+
* - `getGridData()` equivalent;
|
|
33
|
+
* - column mapping (`field, headerText, type, isPrimaryKey, width,
|
|
34
|
+
* format (date default 'MM/dd/yyyy'), editType, allowEditing`);
|
|
35
|
+
* - `filterSettings.mode='Immediate'`.
|
|
36
|
+
*/
|
|
37
|
+
var DataGridComponent = /** @class */ (function () {
|
|
38
|
+
function DataGridComponent(options) {
|
|
39
|
+
var _this = this;
|
|
40
|
+
this.grid = null;
|
|
41
|
+
this.wrapper = null;
|
|
42
|
+
/**
|
|
43
|
+
* Map React custom validation to a Syncfusion-style custom validator
|
|
44
|
+
* closure. Mirrors `mapCustomValidationToSyncfusion`.
|
|
45
|
+
*/
|
|
46
|
+
this.mapCustomValidationToSyncfusion = function (col) {
|
|
47
|
+
if (!col.customValidation || col.customValidation.length === 0) {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
return function (value) {
|
|
51
|
+
var formObj = _this.grid && _this.grid.editModule ? _this.grid.editModule.formObj : null;
|
|
52
|
+
if (!formObj) {
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
var rowContext = {};
|
|
56
|
+
(_this.columns || []).forEach(function (gridCol) {
|
|
57
|
+
var input = formObj.getInputElement(gridCol.field);
|
|
58
|
+
if (input) {
|
|
59
|
+
var v = input.value;
|
|
60
|
+
rowContext[gridCol.field] = gridCol.type === 'number' ? parseInt(v, 10) : v;
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
for (var _i = 0, _a = col.customValidation; _i < _a.length; _i++) {
|
|
64
|
+
var rule = _a[_i];
|
|
65
|
+
if (!rule.expression) {
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
var fieldValue = col.type === 'number' ? parseInt(value.value, 10) : value.value;
|
|
69
|
+
var result = _this.validationEngine.validate(rule.expression, fieldValue, rowContext);
|
|
70
|
+
return result === true;
|
|
71
|
+
}
|
|
72
|
+
return true;
|
|
73
|
+
};
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* Create edit params attaching a `change` callback for non-calculated
|
|
77
|
+
* columns that have calc dependents. Mirrors `createEditParams`.
|
|
78
|
+
*/
|
|
79
|
+
this.createEditParams = function (col) {
|
|
80
|
+
if (!_this.hasExpressions) {
|
|
81
|
+
return undefined;
|
|
82
|
+
}
|
|
83
|
+
var calculatedCols = _this.calculatedColumns;
|
|
84
|
+
var hasDependents = calculatedCols.some(function (calcCol) {
|
|
85
|
+
if (!calcCol.expression) {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
return calcCol.expression.indexOf("{" + col.field + "}") !== -1;
|
|
89
|
+
});
|
|
90
|
+
if (!hasDependents) {
|
|
91
|
+
return undefined;
|
|
92
|
+
}
|
|
93
|
+
return {
|
|
94
|
+
params: {
|
|
95
|
+
change: function () {
|
|
96
|
+
if (!_this.grid || !_this.grid.element) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
var form = _this.grid.element.querySelector('form');
|
|
100
|
+
if (!form || !form.ej2_instances || !form.ej2_instances[0]) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
var formInstance = form.ej2_instances[0];
|
|
104
|
+
calculatedCols.forEach(function (calcCol) {
|
|
105
|
+
var input = formInstance.getInputElement(calcCol.field);
|
|
106
|
+
if (!input) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
try {
|
|
110
|
+
var rowValues_1 = {};
|
|
111
|
+
_this.columns.forEach(function (c) {
|
|
112
|
+
var fieldInput = formInstance.getInputElement(c.field);
|
|
113
|
+
if (fieldInput) {
|
|
114
|
+
rowValues_1[c.field] = fieldInput.value;
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
var result = _this.gridExpressions.evaluateRowExpressions(rowValues_1, _this.columns);
|
|
118
|
+
var calculatedValue = result[calcCol.field];
|
|
119
|
+
if (calculatedValue !== undefined && calculatedValue !== null) {
|
|
120
|
+
if (calcCol.type === 'boolean') {
|
|
121
|
+
input.checked = !!calculatedValue;
|
|
122
|
+
}
|
|
123
|
+
else if (calcCol.type === 'number') {
|
|
124
|
+
var wrapper = input.closest('.e-control-wrapper');
|
|
125
|
+
var numericInput = wrapper ? wrapper.querySelector('input.e-control:not([type="hidden"])') : null;
|
|
126
|
+
if (numericInput && numericInput.ej2_instances && numericInput.ej2_instances[0]) {
|
|
127
|
+
numericInput.ej2_instances[0].value = calculatedValue;
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
input.value = calculatedValue;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
else if (calcCol.type === 'date') {
|
|
134
|
+
input.ej2_instances[0].value = new Date(calculatedValue);
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
input.value = calculatedValue;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
catch (_a) {
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
};
|
|
148
|
+
/**
|
|
149
|
+
* Sync the working data on `actionComplete`. Mirrors `handleActionComplete`.
|
|
150
|
+
*/
|
|
151
|
+
this.handleActionComplete = function (args) {
|
|
152
|
+
if (!_this.grid) {
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
var eventType = args.requestType;
|
|
156
|
+
switch (eventType) {
|
|
157
|
+
case 'save':
|
|
158
|
+
case 'delete':
|
|
159
|
+
case 'add': {
|
|
160
|
+
if (_this.grid.dataSource) {
|
|
161
|
+
var updatedData = Array.isArray(_this.grid.dataSource)
|
|
162
|
+
? _this.grid.dataSource
|
|
163
|
+
: [];
|
|
164
|
+
_this.currentData = updatedData;
|
|
165
|
+
if (_this.onDataChange) {
|
|
166
|
+
_this.onDataChange(updatedData);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
break;
|
|
170
|
+
}
|
|
171
|
+
default:
|
|
172
|
+
break;
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
this.id = options.id;
|
|
176
|
+
this.columns = options.columns || [];
|
|
177
|
+
this.dataSource = Array.isArray(options.dataSource) ? options.dataSource : [];
|
|
178
|
+
this.height = options.height != null ? options.height : '200px';
|
|
179
|
+
this.width = options.width != null ? options.width : '100%';
|
|
180
|
+
this.locale = options.locale;
|
|
181
|
+
this.cssClass = options.cssClass;
|
|
182
|
+
this.pageSize = options.pageSize != null ? options.pageSize : 6;
|
|
183
|
+
this.allowPaging = options.allowPaging !== false;
|
|
184
|
+
this.allowAdding = options.allowAdding !== false;
|
|
185
|
+
this.allowEditing = options.allowEditing !== false;
|
|
186
|
+
this.allowDeleting = options.allowDeleting !== false;
|
|
187
|
+
this.allowFiltering = options.allowFiltering === true;
|
|
188
|
+
this.onDataChange = options.onDataChange;
|
|
189
|
+
this.isPreviewMode = options.isPreviewMode;
|
|
190
|
+
this.enableRtl = options.enableRtl;
|
|
191
|
+
this.ref = options.ref;
|
|
192
|
+
this.currentData = Array.isArray(this.dataSource) ? this.dataSource : [];
|
|
193
|
+
this.gridExpressions = new GridExpressions();
|
|
194
|
+
this.validationEngine = new CustomValidationEngine();
|
|
195
|
+
}
|
|
196
|
+
Object.defineProperty(DataGridComponent.prototype, "calculatedColumns", {
|
|
197
|
+
get: function () {
|
|
198
|
+
return this.gridExpressions.extractCalculatedColumns(this.columns);
|
|
199
|
+
},
|
|
200
|
+
enumerable: true,
|
|
201
|
+
configurable: true
|
|
202
|
+
});
|
|
203
|
+
Object.defineProperty(DataGridComponent.prototype, "hasExpressions", {
|
|
204
|
+
get: function () {
|
|
205
|
+
return this.calculatedColumns.length > 0;
|
|
206
|
+
},
|
|
207
|
+
enumerable: true,
|
|
208
|
+
configurable: true
|
|
209
|
+
});
|
|
210
|
+
/**
|
|
211
|
+
* Build the dynamic toolbar array. Mirrors `buildToolbar`.
|
|
212
|
+
*/
|
|
213
|
+
DataGridComponent.prototype.buildToolbar = function () {
|
|
214
|
+
var items = [];
|
|
215
|
+
if (this.allowAdding) {
|
|
216
|
+
items.push('Add');
|
|
217
|
+
}
|
|
218
|
+
if (this.allowEditing) {
|
|
219
|
+
items.push('Edit');
|
|
220
|
+
}
|
|
221
|
+
if (this.allowDeleting) {
|
|
222
|
+
items.push('Delete');
|
|
223
|
+
}
|
|
224
|
+
items.push('Update', 'Cancel');
|
|
225
|
+
return items;
|
|
226
|
+
};
|
|
227
|
+
/**
|
|
228
|
+
* Map a GridColumn to the EJ2 Grid column model, merging standard + custom
|
|
229
|
+
* validation rules and disabling editing on expression / no-edit columns.
|
|
230
|
+
*/
|
|
231
|
+
DataGridComponent.prototype.mapColumn = function (col) {
|
|
232
|
+
var validationRules = col.validationRules ? __assign({}, col.validationRules) : {};
|
|
233
|
+
var customValidator = this.mapCustomValidationToSyncfusion(col);
|
|
234
|
+
if (customValidator) {
|
|
235
|
+
var errorMessage = col.customValidation && col.customValidation[0] && col.customValidation[0].expression
|
|
236
|
+
? (this.validationEngine.parseExpression
|
|
237
|
+
? this.validationEngine.parseExpression(col.customValidation[0].expression).errorMessage
|
|
238
|
+
: 'Validation failed') || 'Validation failed'
|
|
239
|
+
: 'Validation failed';
|
|
240
|
+
validationRules.required = [true, errorMessage];
|
|
241
|
+
validationRules.custom = [customValidator, errorMessage];
|
|
242
|
+
}
|
|
243
|
+
return {
|
|
244
|
+
field: col.field,
|
|
245
|
+
headerText: col.headerText,
|
|
246
|
+
type: col.type || 'string',
|
|
247
|
+
isPrimaryKey: col.isPrimaryKey || false,
|
|
248
|
+
width: col.width,
|
|
249
|
+
format: col.type === 'date' ? (col.format || 'MM/dd/yyyy') : col.format,
|
|
250
|
+
editType: col.editType,
|
|
251
|
+
allowEditing: col.allowEditing !== false && !col.expression,
|
|
252
|
+
validationRules: validationRules,
|
|
253
|
+
edit: this.createEditParams(col)
|
|
254
|
+
};
|
|
255
|
+
};
|
|
256
|
+
/**
|
|
257
|
+
* Build the grid element, instantiate `Grid`, inject services and append
|
|
258
|
+
* to the target/created container. Returns the wrapper element.
|
|
259
|
+
*/
|
|
260
|
+
DataGridComponent.prototype.render = function (targetOrHost) {
|
|
261
|
+
var _this = this;
|
|
262
|
+
// Normalize initial currentData with expression evaluation
|
|
263
|
+
var normalized = Array.isArray(this.dataSource) ? this.dataSource : [];
|
|
264
|
+
if (this.hasExpressions && normalized.length > 0) {
|
|
265
|
+
this.currentData = normalized.map(function (row) {
|
|
266
|
+
var result = _this.gridExpressions.evaluateRowExpressions(row, _this.columns);
|
|
267
|
+
return __assign({}, row, result);
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
else {
|
|
271
|
+
this.currentData = normalized;
|
|
272
|
+
}
|
|
273
|
+
var wrapper = document.createElement('div');
|
|
274
|
+
wrapper.className = 'datagrid-wrapper';
|
|
275
|
+
wrapper.style.width = typeof this.width === 'string' ? this.width : this.width + "px";
|
|
276
|
+
wrapper.style.height = 'auto';
|
|
277
|
+
var gridHost = document.createElement('div');
|
|
278
|
+
gridHost.className = 'datagrid-grid';
|
|
279
|
+
wrapper.appendChild(gridHost);
|
|
280
|
+
if (this.id) {
|
|
281
|
+
gridHost.id = this.id;
|
|
282
|
+
}
|
|
283
|
+
var grid = new Grid({
|
|
284
|
+
dataSource: this.currentData,
|
|
285
|
+
allowPaging: this.allowPaging,
|
|
286
|
+
filterSettings: { mode: 'Immediate' },
|
|
287
|
+
pageSettings: { pageSize: this.pageSize },
|
|
288
|
+
editSettings: {
|
|
289
|
+
allowEditing: this.allowEditing,
|
|
290
|
+
allowAdding: this.allowAdding,
|
|
291
|
+
allowDeleting: this.allowDeleting,
|
|
292
|
+
mode: 'Normal'
|
|
293
|
+
},
|
|
294
|
+
enableRtl: this.enableRtl,
|
|
295
|
+
locale: this.locale || 'en-US',
|
|
296
|
+
cssClass: this.cssClass,
|
|
297
|
+
toolbar: this.buildToolbar(),
|
|
298
|
+
actionComplete: this.handleActionComplete,
|
|
299
|
+
height: typeof this.height === 'string' ? this.height : this.height + "px",
|
|
300
|
+
width: typeof this.width === 'string' ? this.width : this.width + "px",
|
|
301
|
+
allowSorting: true,
|
|
302
|
+
allowFiltering: this.allowFiltering,
|
|
303
|
+
allowSelection: true,
|
|
304
|
+
columns: (this.columns || []).map(function (c) { return _this.mapColumn(c); })
|
|
305
|
+
});
|
|
306
|
+
grid.appendTo(gridHost);
|
|
307
|
+
this.ref(grid);
|
|
308
|
+
// Inject the required modules into the Grid prototype (executed once
|
|
309
|
+
// at module load — see the static `Grid.Inject(...)` call at the
|
|
310
|
+
// bottom of this file).
|
|
311
|
+
this.grid = grid;
|
|
312
|
+
if (targetOrHost) {
|
|
313
|
+
targetOrHost.appendChild(wrapper);
|
|
314
|
+
}
|
|
315
|
+
this.wrapper = wrapper;
|
|
316
|
+
return wrapper;
|
|
317
|
+
};
|
|
318
|
+
/**
|
|
319
|
+
* @private
|
|
320
|
+
*/
|
|
321
|
+
DataGridComponent.prototype.getRef = function () {
|
|
322
|
+
var _this = this;
|
|
323
|
+
return {
|
|
324
|
+
getGridData: function () { return _this.currentData; },
|
|
325
|
+
gridRef: { current: this.grid }
|
|
326
|
+
};
|
|
327
|
+
};
|
|
328
|
+
/**
|
|
329
|
+
* Equivalent of `getGridData()`.
|
|
330
|
+
*/
|
|
331
|
+
DataGridComponent.prototype.getGridData = function () {
|
|
332
|
+
return this.currentData;
|
|
333
|
+
};
|
|
334
|
+
/**
|
|
335
|
+
* Recompute expression-bearing rows from fresh `dataSource` (mirrors the
|
|
336
|
+
* useEffect on `[dataSource, hasExpressions, columns, ...]`).
|
|
337
|
+
*/
|
|
338
|
+
DataGridComponent.prototype.setDataSource = function (dataSource) {
|
|
339
|
+
var _this = this;
|
|
340
|
+
if (!this.grid) {
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
var normalized = Array.isArray(dataSource) ? dataSource : [];
|
|
344
|
+
if (this.hasExpressions && normalized.length > 0) {
|
|
345
|
+
this.currentData = normalized.map(function (row) {
|
|
346
|
+
var r = _this.gridExpressions.evaluateRowExpressions(row, _this.columns);
|
|
347
|
+
return __assign({}, row, r);
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
else {
|
|
351
|
+
this.currentData = normalized;
|
|
352
|
+
}
|
|
353
|
+
this.grid.dataSource = this.currentData;
|
|
354
|
+
if (this.grid.refreshBatchData) {
|
|
355
|
+
this.grid.setProperties({ dataSource: this.currentData }, true);
|
|
356
|
+
}
|
|
357
|
+
else {
|
|
358
|
+
this.grid.dataSource = this.currentData;
|
|
359
|
+
}
|
|
360
|
+
if (this.grid.refresh) {
|
|
361
|
+
this.grid.refresh();
|
|
362
|
+
}
|
|
363
|
+
};
|
|
364
|
+
/**
|
|
365
|
+
* Re-detect columns; refresh the grid (mirrors the useEffect on columns).
|
|
366
|
+
*/
|
|
367
|
+
DataGridComponent.prototype.setColumns = function (columns) {
|
|
368
|
+
if (!this.grid) {
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
371
|
+
if (!columns || columns.length === 0) {
|
|
372
|
+
this.grid.columns = [];
|
|
373
|
+
}
|
|
374
|
+
else if (this.grid.columns.length === 0 && columns && columns.length === 1) {
|
|
375
|
+
this.grid.columns = columns;
|
|
376
|
+
}
|
|
377
|
+
this.columns = columns;
|
|
378
|
+
if (this.grid.refresh && !this.isPreviewMode) {
|
|
379
|
+
if (this.dataSource && Array.isArray(this.dataSource) && this.dataSource.length > 0 && !this.hasExpressions) {
|
|
380
|
+
this.grid.dataSource = this.dataSource;
|
|
381
|
+
}
|
|
382
|
+
this.grid.refresh();
|
|
383
|
+
}
|
|
384
|
+
};
|
|
385
|
+
/**
|
|
386
|
+
* @private
|
|
387
|
+
*/
|
|
388
|
+
DataGridComponent.prototype.destroy = function () {
|
|
389
|
+
if (this.grid) {
|
|
390
|
+
try {
|
|
391
|
+
this.grid.destroy();
|
|
392
|
+
}
|
|
393
|
+
catch (e) { /* ignore */ }
|
|
394
|
+
this.grid = null;
|
|
395
|
+
}
|
|
396
|
+
if (this.wrapper && this.wrapper.parentNode) {
|
|
397
|
+
this.wrapper.parentNode.removeChild(this.wrapper);
|
|
398
|
+
}
|
|
399
|
+
this.wrapper = null;
|
|
400
|
+
this.gridExpressions = null;
|
|
401
|
+
this.validationEngine = null;
|
|
402
|
+
this.currentData = [];
|
|
403
|
+
this.columns = [];
|
|
404
|
+
this.dataSource = [];
|
|
405
|
+
};
|
|
406
|
+
return DataGridComponent;
|
|
407
|
+
}());
|
|
408
|
+
export { DataGridComponent };
|
|
409
|
+
export default DataGridComponent;
|
|
410
|
+
Grid.Inject(Edit, Toolbar, Page, Resize, Sort, Filter);
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DependencyTracker - Extract and track field dependencies
|
|
3
|
+
*
|
|
4
|
+
* Analyzes expressions to find field references and build dependency graphs
|
|
5
|
+
* Detects circular dependencies and calculates evaluation order
|
|
6
|
+
* @private
|
|
7
|
+
*/
|
|
8
|
+
export declare class DependencyTracker {
|
|
9
|
+
private escapedBracePattern;
|
|
10
|
+
/**
|
|
11
|
+
* Extract field names referenced in expression
|
|
12
|
+
*/
|
|
13
|
+
extractFieldReferences(expression: string): string[];
|
|
14
|
+
/**
|
|
15
|
+
* Build dependency graph from multiple expressions
|
|
16
|
+
*/
|
|
17
|
+
buildGraph(expressions: Record<string, string>): Record<string, string[]>;
|
|
18
|
+
/**
|
|
19
|
+
* Detect circular dependencies using DFS
|
|
20
|
+
*/
|
|
21
|
+
detectCircularDependencies(graph: Record<string, string[]>): string[][];
|
|
22
|
+
/**
|
|
23
|
+
* Get topological sort order for evaluation
|
|
24
|
+
*/
|
|
25
|
+
getTopologicalOrder(graph: Record<string, string[]>): string[];
|
|
26
|
+
private isFunctionCall;
|
|
27
|
+
private isOperator;
|
|
28
|
+
private isKeyword;
|
|
29
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DependencyTracker - Extract and track field dependencies
|
|
3
|
+
*
|
|
4
|
+
* Analyzes expressions to find field references and build dependency graphs
|
|
5
|
+
* Detects circular dependencies and calculates evaluation order
|
|
6
|
+
* @private
|
|
7
|
+
*/
|
|
8
|
+
var DependencyTracker = /** @class */ (function () {
|
|
9
|
+
function DependencyTracker() {
|
|
10
|
+
this.escapedBracePattern = /\\{.*?\\}/g;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Extract field names referenced in expression
|
|
14
|
+
*/
|
|
15
|
+
DependencyTracker.prototype.extractFieldReferences = function (expression) {
|
|
16
|
+
if (!expression)
|
|
17
|
+
return [];
|
|
18
|
+
var refs = new Set();
|
|
19
|
+
var match;
|
|
20
|
+
// Remove escaped braces first
|
|
21
|
+
var cleanExpression = expression.replace(this.escapedBracePattern, '');
|
|
22
|
+
// Extract field references from {field} syntax
|
|
23
|
+
var fieldRefPattern = /\{([^{}]+)\}/g;
|
|
24
|
+
while ((match = fieldRefPattern.exec(cleanExpression)) !== null) {
|
|
25
|
+
var ref = match[1].trim();
|
|
26
|
+
// Skip if it's a function call or operator
|
|
27
|
+
if (!this.isFunctionCall(ref) && !this.isOperator(ref)) {
|
|
28
|
+
// Extract field name from nested paths
|
|
29
|
+
var fieldName = ref.split(/[.\[\]]/)[0].trim();
|
|
30
|
+
if (fieldName && !this.isKeyword(fieldName)) {
|
|
31
|
+
refs.add(fieldName);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
// Extract identifiers from ${...} math expressions
|
|
36
|
+
var mathExprPattern = /\$\{([^}]+)\}/g;
|
|
37
|
+
while ((match = mathExprPattern.exec(cleanExpression)) !== null) {
|
|
38
|
+
var mathExpr = match[1];
|
|
39
|
+
// Extract all identifiers from the math expression
|
|
40
|
+
// Match word boundaries followed by identifier characters
|
|
41
|
+
// But skip if followed by ( or . (those are function calls or property access)
|
|
42
|
+
var identPattern = /\b([a-zA-Z_][a-zA-Z0-9_]*)\b(?!\s*[(\.])/g;
|
|
43
|
+
var idMatch = void 0;
|
|
44
|
+
while ((idMatch = identPattern.exec(mathExpr)) !== null) {
|
|
45
|
+
var identifier = idMatch[1];
|
|
46
|
+
// Skip keywords and constants
|
|
47
|
+
if (!this.isKeyword(identifier) && identifier !== 'Math') {
|
|
48
|
+
refs.add(identifier);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return Array.from(refs);
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Build dependency graph from multiple expressions
|
|
56
|
+
*/
|
|
57
|
+
DependencyTracker.prototype.buildGraph = function (expressions) {
|
|
58
|
+
var graph = {};
|
|
59
|
+
var keys = Object.keys(expressions);
|
|
60
|
+
for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) {
|
|
61
|
+
var fieldName = keys_1[_i];
|
|
62
|
+
var deps = this.extractFieldReferences(expressions[fieldName]);
|
|
63
|
+
graph[fieldName] = deps;
|
|
64
|
+
}
|
|
65
|
+
return graph;
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* Detect circular dependencies using DFS
|
|
69
|
+
*/
|
|
70
|
+
DependencyTracker.prototype.detectCircularDependencies = function (graph) {
|
|
71
|
+
var visited = new Set();
|
|
72
|
+
var recursionStack = new Set();
|
|
73
|
+
var cycles = [];
|
|
74
|
+
var visit = function (node, path) {
|
|
75
|
+
visited.add(node);
|
|
76
|
+
recursionStack.add(node);
|
|
77
|
+
path.push(node);
|
|
78
|
+
var deps = graph[node] || [];
|
|
79
|
+
for (var _i = 0, deps_1 = deps; _i < deps_1.length; _i++) {
|
|
80
|
+
var dep = deps_1[_i];
|
|
81
|
+
if (!visited.has(dep)) {
|
|
82
|
+
visit(dep, path.slice());
|
|
83
|
+
}
|
|
84
|
+
else if (recursionStack.has(dep)) {
|
|
85
|
+
var cycleStart = path.indexOf(dep);
|
|
86
|
+
cycles.push(path.slice(cycleStart).concat([dep]));
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
recursionStack.delete(node);
|
|
90
|
+
};
|
|
91
|
+
for (var _i = 0, _a = Object.keys(graph); _i < _a.length; _i++) {
|
|
92
|
+
var node = _a[_i];
|
|
93
|
+
if (!visited.has(node)) {
|
|
94
|
+
visit(node, []);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return cycles;
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* Get topological sort order for evaluation
|
|
101
|
+
*/
|
|
102
|
+
DependencyTracker.prototype.getTopologicalOrder = function (graph) {
|
|
103
|
+
var visited = new Set();
|
|
104
|
+
var order = [];
|
|
105
|
+
var visit = function (node) {
|
|
106
|
+
if (visited.has(node))
|
|
107
|
+
return;
|
|
108
|
+
visited.add(node);
|
|
109
|
+
var deps = graph[node] || [];
|
|
110
|
+
for (var _i = 0, deps_2 = deps; _i < deps_2.length; _i++) {
|
|
111
|
+
var dep = deps_2[_i];
|
|
112
|
+
if (graph[dep]) {
|
|
113
|
+
visit(dep);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
order.push(node);
|
|
117
|
+
};
|
|
118
|
+
for (var _i = 0, _a = Object.keys(graph); _i < _a.length; _i++) {
|
|
119
|
+
var node = _a[_i];
|
|
120
|
+
visit(node);
|
|
121
|
+
}
|
|
122
|
+
return order;
|
|
123
|
+
};
|
|
124
|
+
// Private helpers
|
|
125
|
+
DependencyTracker.prototype.isFunctionCall = function (ref) {
|
|
126
|
+
return /^\w+\s*\(/.test(ref);
|
|
127
|
+
};
|
|
128
|
+
DependencyTracker.prototype.isOperator = function (ref) {
|
|
129
|
+
return /^[+\-*/()=!<>&|]/.test(ref);
|
|
130
|
+
};
|
|
131
|
+
DependencyTracker.prototype.isKeyword = function (name) {
|
|
132
|
+
var keywords = ['PI', 'TRUE', 'FALSE', 'NULL', 'UNDEFINED', 'and', 'or', 'in'];
|
|
133
|
+
return keywords.indexOf(name.toUpperCase()) !== -1;
|
|
134
|
+
};
|
|
135
|
+
return DependencyTracker;
|
|
136
|
+
}());
|
|
137
|
+
export { DependencyTracker };
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @private
|
|
3
|
+
*/
|
|
4
|
+
export declare type FormValueType = string | number | boolean | Date | null | undefined | any[];
|
|
5
|
+
/**
|
|
6
|
+
* @private
|
|
7
|
+
*/
|
|
8
|
+
export interface EvaluationOptions {
|
|
9
|
+
timeout?: number;
|
|
10
|
+
maxDepth?: number;
|
|
11
|
+
locale?: string;
|
|
12
|
+
currencyCode?: string;
|
|
13
|
+
throwOnError?: boolean;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* @private
|
|
17
|
+
*/
|
|
18
|
+
export declare type DependencyGraph = Record<string, string[]>;
|
|
19
|
+
/**
|
|
20
|
+
* ExpressionEngine - Core evaluation engine
|
|
21
|
+
*
|
|
22
|
+
* Safely evaluates user-defined expressions against form state
|
|
23
|
+
* Supports field references, math operations, functions, and conditionals
|
|
24
|
+
* @private
|
|
25
|
+
*/
|
|
26
|
+
export declare class ExpressionEngine {
|
|
27
|
+
private parser;
|
|
28
|
+
private dependencyTracker;
|
|
29
|
+
private evaluationCache;
|
|
30
|
+
private compiledFunctions;
|
|
31
|
+
constructor();
|
|
32
|
+
/**
|
|
33
|
+
* Evaluate expression against form values
|
|
34
|
+
*/
|
|
35
|
+
evaluate(expression: string, formValues: Record<string, FormValueType>, options?: EvaluationOptions, isCustomValidation?: boolean): any;
|
|
36
|
+
/**
|
|
37
|
+
* Extract field names referenced in expression
|
|
38
|
+
*/
|
|
39
|
+
extractDependencies(expression: string): string[];
|
|
40
|
+
/**
|
|
41
|
+
* Build dependency graph for all expressions
|
|
42
|
+
*/
|
|
43
|
+
buildDependencyGraph(components: any[]): DependencyGraph;
|
|
44
|
+
/**
|
|
45
|
+
* Detect circular dependencies
|
|
46
|
+
*/
|
|
47
|
+
detectCircularDependencies(graph: DependencyGraph): string[][];
|
|
48
|
+
/**
|
|
49
|
+
* Get topological order for evaluation
|
|
50
|
+
*/
|
|
51
|
+
getTopologicalOrder(graph: DependencyGraph): string[];
|
|
52
|
+
/**
|
|
53
|
+
* Clear internal caches
|
|
54
|
+
*/
|
|
55
|
+
clearCache(): void;
|
|
56
|
+
private getCacheKey;
|
|
57
|
+
private buildContext;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* ExpressionValidator - Validates expressions before runtime
|
|
61
|
+
*
|
|
62
|
+
* Checks syntax, validates field references, and detects circular dependencies
|
|
63
|
+
* @private
|
|
64
|
+
*/
|
|
65
|
+
export declare class ExpressionValidator {
|
|
66
|
+
private supportedFunctions;
|
|
67
|
+
private keywords;
|
|
68
|
+
/**
|
|
69
|
+
* Validate expression against available fields
|
|
70
|
+
*/
|
|
71
|
+
validate(expression: string, availableFields: string[] | any[]): ValidationError[];
|
|
72
|
+
/**
|
|
73
|
+
* Validate field operations - check for invalid operators on string/date types
|
|
74
|
+
*/
|
|
75
|
+
private validateFieldOperations;
|
|
76
|
+
private validateSyntax;
|
|
77
|
+
/**
|
|
78
|
+
* @private
|
|
79
|
+
*/
|
|
80
|
+
validateFieldReferences(expression: string, availableFields: string[] | any[]): ValidationError[];
|
|
81
|
+
private validateFunctionCalls;
|
|
82
|
+
private isFunctionCall;
|
|
83
|
+
private isMathExpression;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* @private
|
|
87
|
+
*/
|
|
88
|
+
export interface ValidationError {
|
|
89
|
+
type: 'SyntaxError' | 'UndefinedField' | 'InvalidFunction' | 'CircularDependency' | 'InvalidOperation';
|
|
90
|
+
message: string;
|
|
91
|
+
field?: string;
|
|
92
|
+
line?: number;
|
|
93
|
+
column?: number;
|
|
94
|
+
}
|