@cdmx/wappler_ag_grid 2.1.3 → 2.1.5
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/.claude/settings.json +7 -0
- package/CHANGELOG.md +23 -1
- package/app_connect/components.hjson +6 -5
- package/dmx-ag-grid.js +37 -12
- package/package.json +5 -2
- package/tests/01-basic-render.html +106 -0
- package/tests/02-themes-locale.html +98 -0
- package/tests/03-editing.html +119 -0
- package/tests/04-selection.html +103 -0
- package/tests/05-action-buttons.html +97 -0
- package/tests/06-export.html +80 -0
- package/tests/07-import.html +80 -0
- package/tests/08-formatting.html +91 -0
- package/tests/09-grouping.html +74 -0
- package/tests/10-state-persistence.html +84 -0
- package/tests/11-layout.html +72 -0
- package/tests/12-methods.html +93 -0
- package/tests/13-flags-styles.html +374 -0
- package/tests/14-compact-view.html +112 -0
- package/tests/README.md +146 -0
- package/tests/data/sample-data.js +52 -0
- package/tests/dmxAppConnect/dmxAppConnect.js +10 -0
- package/tests/dmxAppConnect/dmxAppConnect.js.map +1 -0
- package/tests/index.html +107 -0
- package/tests/lib/common-head.html +30 -0
- package/tests/lib/page-template.js +54 -0
- package/tests/lib/run-collector.js +32 -0
- package/tests/lib/test-helpers.js +145 -0
- package/tests/lib/test-suite.css +178 -0
- package/tests/run-all-puppeteer.cjs +180 -0
- package/tests/run-all.cjs +144 -0
- package/tests/serve.cjs +66 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,26 @@
|
|
|
1
|
-
# Change Log
|
|
1
|
+
# Change Log
|
|
2
|
+
|
|
3
|
+
## Version 2.1.4 (Row Color Formatting Fix)
|
|
4
|
+
|
|
5
|
+
### Summary
|
|
6
|
+
Fixed row color styling (`rstyles`) so it works dynamically, supports multiple colors for the
|
|
7
|
+
same field, and can color rows directly by field value.
|
|
8
|
+
|
|
9
|
+
### Changes Made
|
|
10
|
+
1. **`app_connect/components.hjson`** - removed `"key": "field"` from the "Configure Row Colors"
|
|
11
|
+
grid so it serializes as an array (unlimited rows per field). Renamed the `condition` column to
|
|
12
|
+
"Condition" and documented the supported syntax.
|
|
13
|
+
2. **`dmx-ag-grid.js`** - changed the `rstyles` prop default from `{}` to `[]`, and rewrote
|
|
14
|
+
`createRowStyleFunction` to mirror the cell-style path: it normalizes both array and legacy
|
|
15
|
+
object input (backward compatible), and evaluates value/operator expressions
|
|
16
|
+
(`status == active`, `amount > 1000`, compound `&&`/`||`), function conditions (`myFn()`), and a
|
|
17
|
+
Field + plain-value exact-match shorthand. First matching condition wins.
|
|
18
|
+
3. **`dmx-ag-grid.js`** - fixed operator parsing in `extractConditionParts` so `>=` and `<=`
|
|
19
|
+
are no longer mis-parsed as `>`/`<` (this also fixes `>=`/`<=` conditions in cell styles).
|
|
20
|
+
Function conditions require trailing `()` so plain shorthand values (e.g. status `open`)
|
|
21
|
+
cannot collide with `window` built-ins like `window.open`.
|
|
22
|
+
|
|
23
|
+
---
|
|
2
24
|
|
|
3
25
|
## Version 2.0.15 (HTML Export Removal Added)
|
|
4
26
|
|
|
@@ -808,14 +808,13 @@
|
|
|
808
808
|
],
|
|
809
809
|
"noChangeOnHide": true,
|
|
810
810
|
"groupEnabler": true,
|
|
811
|
-
"help": "Add
|
|
811
|
+
"help": "Color whole rows by condition. Add one row per color - the same field can have many. Condition supports value/operator expressions (e.g. status == active, amount > 1000, status == open && amount > 100), a function name returning a boolean (e.g. myFn()), or - as a shorthand - a Field plus a plain value for an exact match. Values are unquoted."
|
|
812
812
|
"children": [
|
|
813
813
|
{
|
|
814
814
|
"name": "listRowColors",
|
|
815
815
|
"attribute": "dmx-bind:rstyles",
|
|
816
816
|
"title": "Row Colors",
|
|
817
817
|
"type": "grid",
|
|
818
|
-
"key": "field",
|
|
819
818
|
"dataBindings": true,
|
|
820
819
|
"jsonFormat": true,
|
|
821
820
|
"encloseBT": true,
|
|
@@ -827,14 +826,16 @@
|
|
|
827
826
|
"caption": "Field",
|
|
828
827
|
"editable": {
|
|
829
828
|
"type": "text"
|
|
830
|
-
}
|
|
829
|
+
},
|
|
830
|
+
help: "Optional. Used with the shorthand (Field + plain value in Condition) for an exact match."
|
|
831
831
|
},
|
|
832
832
|
{
|
|
833
833
|
"field": "condition",
|
|
834
|
-
"caption": "
|
|
834
|
+
"caption": "Condition",
|
|
835
835
|
"editable": {
|
|
836
836
|
"type": "text"
|
|
837
|
-
}
|
|
837
|
+
},
|
|
838
|
+
help: "Expression (status == active, amount > 1000, a && b), function name with trailing parentheses (myFn() - the () are required), or a plain value matched against Field. Values are unquoted."
|
|
838
839
|
},
|
|
839
840
|
{
|
|
840
841
|
"field": "customColor",
|
package/dmx-ag-grid.js
CHANGED
|
@@ -24,7 +24,7 @@ dmx.Component('ag-grid', {
|
|
|
24
24
|
tooltip_config: { type: Array, default: [] },
|
|
25
25
|
custom_tooltip: { type: String, default: null },
|
|
26
26
|
cstyles: { type: Array, default: [] },
|
|
27
|
-
rstyles: { type: Array, default:
|
|
27
|
+
rstyles: { type: Array, default: [] },
|
|
28
28
|
cnames: { type: Object, default: {} },
|
|
29
29
|
cwidths: { type: Object, default: {} },
|
|
30
30
|
ctypes: { type: Array, default: [] },
|
|
@@ -850,7 +850,8 @@ dmx.Component('ag-grid', {
|
|
|
850
850
|
|
|
851
851
|
function extractConditionParts(condition) {
|
|
852
852
|
|
|
853
|
-
|
|
853
|
+
// Multi-char operators must be checked before '>' / '<' so '>=' and '<=' parse correctly
|
|
854
|
+
const operators = ['===', '==', '!=', '>=', '<=', '>', '<'];
|
|
854
855
|
let operator;
|
|
855
856
|
let left;
|
|
856
857
|
let right;
|
|
@@ -1065,27 +1066,51 @@ dmx.Component('ag-grid', {
|
|
|
1065
1066
|
//Custom Row Styles
|
|
1066
1067
|
function createRowStyleFunction(rstyles) {
|
|
1067
1068
|
return function(params) {
|
|
1068
|
-
|
|
1069
|
+
// Accept both the array form (current) and the legacy object-keyed-by-field form
|
|
1070
|
+
const styles = Array.isArray(rstyles)
|
|
1071
|
+
? rstyles
|
|
1072
|
+
: (rstyles && typeof rstyles === 'object' ? Object.values(rstyles) : []);
|
|
1073
|
+
if (styles.length === 0) {
|
|
1069
1074
|
return; // No styles to apply
|
|
1070
1075
|
}
|
|
1071
|
-
const
|
|
1072
|
-
|
|
1073
|
-
const condition = style.condition
|
|
1076
|
+
for (const style of styles) {
|
|
1077
|
+
if (!style || !style.customColor) continue;
|
|
1078
|
+
const condition = (style.condition || '').toString().trim();
|
|
1079
|
+
const field = style.field;
|
|
1074
1080
|
const customColor = style.customColor;
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1081
|
+
if (condition === '') continue;
|
|
1082
|
+
let conditionResult = false;
|
|
1083
|
+
|
|
1084
|
+
if (condition.endsWith('()') && typeof window[condition.replace(/\(\)$/, '')] === 'function') {
|
|
1085
|
+
// Function-based condition: receives row data, must return a boolean
|
|
1086
|
+
const result = window[condition.replace(/\(\)$/, '')](params.data);
|
|
1078
1087
|
if (typeof result !== 'boolean') {
|
|
1079
1088
|
console.error('Row condition function must return a boolean value.');
|
|
1080
|
-
|
|
1089
|
+
continue;
|
|
1081
1090
|
}
|
|
1082
1091
|
conditionResult = result;
|
|
1092
|
+
} else if (/(===|==|!=|>=|<=|>|<)/.test(condition)) {
|
|
1093
|
+
// Value/operator expression, with support for compound && / ||
|
|
1094
|
+
if (/&&|\|\|/.test(condition)) {
|
|
1095
|
+
const tokens = condition.split(/\s*(&&|\|\|)\s*/).filter(t => t !== '');
|
|
1096
|
+
conditionResult = evaluateConditions(tokens, params);
|
|
1097
|
+
} else {
|
|
1098
|
+
const [left, operator, right] = extractConditionParts(condition);
|
|
1099
|
+
conditionResult = params.data.hasOwnProperty(left) &&
|
|
1100
|
+
(params.data[left] !== null ? evaluateCondition(params.data[left], operator, right) : false);
|
|
1101
|
+
}
|
|
1102
|
+
} else if (field) {
|
|
1103
|
+
// Shorthand: Field + plain value => exact match on that field's value
|
|
1104
|
+
conditionResult = params.data.hasOwnProperty(field) &&
|
|
1105
|
+
params.data[field] !== null &&
|
|
1106
|
+
String(params.data[field]) === condition;
|
|
1083
1107
|
}
|
|
1108
|
+
|
|
1084
1109
|
if (conditionResult) {
|
|
1085
|
-
|
|
1110
|
+
return { background: customColor }; // first match wins
|
|
1086
1111
|
}
|
|
1087
1112
|
}
|
|
1088
|
-
return
|
|
1113
|
+
return; // no condition matched
|
|
1089
1114
|
};
|
|
1090
1115
|
}
|
|
1091
1116
|
dateFilterParams = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cdmx/wappler_ag_grid",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "App Connect module for AG Grid v35 - Advanced data grid with enhanced editing, filtering, and tree data capabilities.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -16,13 +16,16 @@
|
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"@ag-grid-community/locale": "~35.1.0",
|
|
18
18
|
"ag-grid-community": "~35.1.0",
|
|
19
|
-
"exceljs": "^4.4.0",
|
|
20
19
|
"papaparse": "~5.5.2",
|
|
21
20
|
"pdfmake": "~0.2.18",
|
|
22
21
|
"read-excel-file": "~5.8.7"
|
|
23
22
|
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"exceljs": "github:cdmx-in/exceljs#v4.4.0-uuid11.1.1-r2"
|
|
25
|
+
},
|
|
24
26
|
"scripts": {
|
|
25
27
|
"build": "rollup --config",
|
|
26
28
|
"publish-dry-run": "npm publish ./dist --access public --dry-run"
|
|
27
29
|
}
|
|
28
30
|
}
|
|
31
|
+
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<title>01 · Basic Render · AG Grid Test Suite</title>
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
7
|
+
|
|
8
|
+
<link rel="stylesheet" href="./lib/test-suite.css">
|
|
9
|
+
<link rel="stylesheet" href="../node_modules/ag-grid-community/styles/ag-theme-alpine.css">
|
|
10
|
+
<link rel="stylesheet" href="../ag-theme-custom.css">
|
|
11
|
+
<link rel="stylesheet" href="../switch-toggle-slider.css">
|
|
12
|
+
|
|
13
|
+
<script src="./dmxAppConnect/dmxAppConnect.js" defer></script>
|
|
14
|
+
<script src="./lib/version-banner.js" defer></script>
|
|
15
|
+
<script src="./lib/test-helpers.js" defer></script>
|
|
16
|
+
<script src="./lib/page-template.js" defer></script>
|
|
17
|
+
<script src="../node_modules/ag-grid-community/dist/ag-grid-community.min.js" defer></script>
|
|
18
|
+
<script src="../dmx-ag-grid.js" defer></script>
|
|
19
|
+
<script src="./data/sample-data.js" defer></script>
|
|
20
|
+
</head>
|
|
21
|
+
<body is="dmx-app" id="page01">
|
|
22
|
+
|
|
23
|
+
<script>
|
|
24
|
+
window.addEventListener('DOMContentLoaded', () => {
|
|
25
|
+
TestPage.header({
|
|
26
|
+
title: '01 · Basic Render',
|
|
27
|
+
summary: 'Auto-inferred columns, default sort + text/number filters, floating filter row, pagination.'
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
</script>
|
|
31
|
+
|
|
32
|
+
<main class="test-main">
|
|
33
|
+
|
|
34
|
+
<section class="feature">
|
|
35
|
+
<h2>Default grid — inferred columns</h2>
|
|
36
|
+
<p class="desc">
|
|
37
|
+
Source: <code>window.SampleData.employees</code> (25 rows). The grid infers column types from
|
|
38
|
+
data, renders Alpine theme, pagination size 10, sortable + filterable + floating filter row.
|
|
39
|
+
</p>
|
|
40
|
+
<dmx-test-data id="employees" source="employees"></dmx-test-data>
|
|
41
|
+
|
|
42
|
+
<div class="grid-wrap">
|
|
43
|
+
<dmx-ag-grid
|
|
44
|
+
id="basicGrid"
|
|
45
|
+
dmx-bind:data="employees.value"
|
|
46
|
+
grid_theme="ag-theme-alpine"
|
|
47
|
+
pagination="true"
|
|
48
|
+
dmx-bind:pagination_page_size="10"
|
|
49
|
+
sortable="true"
|
|
50
|
+
filter="true"
|
|
51
|
+
floating_filter="true"
|
|
52
|
+
resizable="true"
|
|
53
|
+
animate_rows="true">
|
|
54
|
+
</dmx-ag-grid>
|
|
55
|
+
</div>
|
|
56
|
+
|
|
57
|
+
<div class="kv">
|
|
58
|
+
<div class="k">Row count (binding)</div>
|
|
59
|
+
<div class="v" id="row-count" dmx-text="basicGrid.count">…</div>
|
|
60
|
+
<div class="k">gridReady</div>
|
|
61
|
+
<div class="v" dmx-text="basicGrid.state.gridReady">…</div>
|
|
62
|
+
<div class="k">firstDataRendered</div>
|
|
63
|
+
<div class="v" dmx-text="basicGrid.state.firstDataRendered">…</div>
|
|
64
|
+
<div class="k">rowDataUpdated</div>
|
|
65
|
+
<div class="v" dmx-text="basicGrid.state.rowDataUpdated">…</div>
|
|
66
|
+
</div>
|
|
67
|
+
|
|
68
|
+
<div class="controls" style="margin-top: 12px;">
|
|
69
|
+
<button class="primary" onclick="TestKit.callMethod('basicGrid', 'reloadGrid', true)">reloadGrid()</button>
|
|
70
|
+
<button onclick="TestKit.callMethod('basicGrid', 'loadGrid')">loadGrid()</button>
|
|
71
|
+
<button onclick="logSnapshot('basicGrid')">log snapshot</button>
|
|
72
|
+
<input type="search" id="qf" placeholder="Quick filter…" oninput="quickFilter(this.value)">
|
|
73
|
+
</div>
|
|
74
|
+
</section>
|
|
75
|
+
|
|
76
|
+
<section class="feature">
|
|
77
|
+
<h2>Console log</h2>
|
|
78
|
+
<div class="log" id="cli-log"></div>
|
|
79
|
+
</section>
|
|
80
|
+
|
|
81
|
+
</main>
|
|
82
|
+
|
|
83
|
+
<script>
|
|
84
|
+
function log(line) {
|
|
85
|
+
const box = document.getElementById('cli-log');
|
|
86
|
+
if (!box) return;
|
|
87
|
+
const el = document.createElement('div');
|
|
88
|
+
el.className = 'log-entry';
|
|
89
|
+
el.textContent = '[' + new Date().toISOString().slice(11,19) + '] ' + line;
|
|
90
|
+
box.insertBefore(el, box.firstChild);
|
|
91
|
+
}
|
|
92
|
+
function logSnapshot(id) {
|
|
93
|
+
log(id + ': ' + JSON.stringify(TestKit.snapshot(id)));
|
|
94
|
+
}
|
|
95
|
+
function quickFilter(value) {
|
|
96
|
+
const g = TestKit.grid('basicGrid');
|
|
97
|
+
if (!g) return;
|
|
98
|
+
const inst = g.get('gridInstance');
|
|
99
|
+
if (inst && inst.setGridOption) {
|
|
100
|
+
inst.setGridOption('quickFilterText', value);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
window.addEventListener('error', (e) => log('error: ' + e.message));
|
|
104
|
+
</script>
|
|
105
|
+
</body>
|
|
106
|
+
</html>
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<title>02 · Themes & Locale · AG Grid Test Suite</title>
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
7
|
+
|
|
8
|
+
<link rel="stylesheet" href="./lib/test-suite.css">
|
|
9
|
+
<link rel="stylesheet" href="../node_modules/ag-grid-community/styles/ag-theme-alpine.css">
|
|
10
|
+
<link rel="stylesheet" href="../node_modules/ag-grid-community/styles/ag-theme-balham.css">
|
|
11
|
+
<link rel="stylesheet" href="../node_modules/ag-grid-community/styles/ag-theme-material.css">
|
|
12
|
+
<link rel="stylesheet" href="../node_modules/ag-grid-community/styles/ag-theme-quartz.css">
|
|
13
|
+
<link rel="stylesheet" href="../ag-theme-custom.css">
|
|
14
|
+
<link rel="stylesheet" href="../switch-toggle-slider.css">
|
|
15
|
+
|
|
16
|
+
<script src="./dmxAppConnect/dmxAppConnect.js" defer></script>
|
|
17
|
+
<script src="./lib/version-banner.js" defer></script>
|
|
18
|
+
<script src="./lib/test-helpers.js" defer></script>
|
|
19
|
+
<script src="./lib/page-template.js" defer></script>
|
|
20
|
+
<script src="../node_modules/ag-grid-community/dist/ag-grid-community.min.js" defer></script>
|
|
21
|
+
<script src="../node_modules/@ag-grid-community/locale/dist/umd/@ag-grid-community/locale.min.js" defer></script>
|
|
22
|
+
<script src="../ru.js" defer></script>
|
|
23
|
+
<script src="../dmx-ag-grid.js" defer></script>
|
|
24
|
+
<script src="./data/sample-data.js" defer></script>
|
|
25
|
+
</head>
|
|
26
|
+
<body is="dmx-app" id="page02">
|
|
27
|
+
|
|
28
|
+
<script>
|
|
29
|
+
window.addEventListener('DOMContentLoaded', () => {
|
|
30
|
+
TestPage.header({
|
|
31
|
+
title: '02 · Themes & Locale',
|
|
32
|
+
summary: 'Toggle theme, dark mode, RTL, locale. The grid re-renders when dark_mode flips.'
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
</script>
|
|
36
|
+
|
|
37
|
+
<main class="test-main">
|
|
38
|
+
<dmx-test-data id="rows" source="employees"></dmx-test-data>
|
|
39
|
+
|
|
40
|
+
<section class="feature">
|
|
41
|
+
<h2>Theme matrix</h2>
|
|
42
|
+
<p class="desc">Each grid is a separate instance, demonstrating that the <code>grid_theme</code> attribute swaps the CSS class.</p>
|
|
43
|
+
|
|
44
|
+
<h3 style="margin-top:14px;">Alpine</h3>
|
|
45
|
+
<div class="grid-wrap"><dmx-ag-grid id="g_alpine" dmx-bind:data="rows.value" grid_theme="ag-theme-alpine" dmx-bind:pagination="false" dmx-bind:row_height="28"></dmx-ag-grid></div>
|
|
46
|
+
|
|
47
|
+
<h3 style="margin-top:14px;">Balham</h3>
|
|
48
|
+
<div class="grid-wrap"><dmx-ag-grid id="g_balham" dmx-bind:data="rows.value" grid_theme="ag-theme-balham" dmx-bind:pagination="false" dmx-bind:row_height="26"></dmx-ag-grid></div>
|
|
49
|
+
|
|
50
|
+
<h3 style="margin-top:14px;">Material</h3>
|
|
51
|
+
<div class="grid-wrap"><dmx-ag-grid id="g_material" dmx-bind:data="rows.value" grid_theme="ag-theme-material" dmx-bind:pagination="false"></dmx-ag-grid></div>
|
|
52
|
+
|
|
53
|
+
<h3 style="margin-top:14px;">Quartz</h3>
|
|
54
|
+
<div class="grid-wrap"><dmx-ag-grid id="g_quartz" dmx-bind:data="rows.value" grid_theme="ag-theme-quartz" dmx-bind:pagination="false"></dmx-ag-grid></div>
|
|
55
|
+
|
|
56
|
+
<h3 style="margin-top:14px;">Custom (alpine + ag-theme-custom)</h3>
|
|
57
|
+
<div class="grid-wrap"><dmx-ag-grid id="g_custom" dmx-bind:data="rows.value" grid_theme="ag-theme-alpine ag-theme-custom" dmx-bind:pagination="false"></dmx-ag-grid></div>
|
|
58
|
+
</section>
|
|
59
|
+
|
|
60
|
+
<section class="feature">
|
|
61
|
+
<h2>Dark mode toggle</h2>
|
|
62
|
+
<p class="desc">Flipping <code>dark_mode</code> triggers the grid's <code>requestUpdate</code> branch and rebuilds the instance with a <code>-dark</code> theme suffix.</p>
|
|
63
|
+
<div class="controls">
|
|
64
|
+
<button class="primary" onclick="toggleDark()">Toggle dark mode</button>
|
|
65
|
+
<span class="kv" style="display:inline-grid; grid-template-columns: auto auto; gap: 4px 8px;">
|
|
66
|
+
<span class="k">dark_mode</span><span class="v" id="dark-val">false</span>
|
|
67
|
+
</span>
|
|
68
|
+
</div>
|
|
69
|
+
<div class="grid-wrap">
|
|
70
|
+
<dmx-ag-grid id="g_dark" dmx-bind:data="rows.value" grid_theme="ag-theme-alpine" dmx-bind:dark_mode="false" dmx-bind:pagination="false"></dmx-ag-grid>
|
|
71
|
+
</div>
|
|
72
|
+
</section>
|
|
73
|
+
|
|
74
|
+
<section class="feature">
|
|
75
|
+
<h2>RTL + locale</h2>
|
|
76
|
+
<p class="desc">Hebrew locale forces RTL; Russian uses the shipped <code>ru.js</code>; Spanish/Portuguese come from <code>@ag-grid-community/locale</code>.</p>
|
|
77
|
+
<h3>Hebrew (RTL)</h3>
|
|
78
|
+
<div class="grid-wrap"><dmx-ag-grid id="g_he" dmx-bind:data="rows.value" grid_theme="ag-theme-alpine" locale_text="HE" dmx-bind:enable_rtl="true" dmx-bind:pagination="false"></dmx-ag-grid></div>
|
|
79
|
+
|
|
80
|
+
<h3 style="margin-top:14px;">Russian</h3>
|
|
81
|
+
<div class="grid-wrap"><dmx-ag-grid id="g_ru" dmx-bind:data="rows.value" grid_theme="ag-theme-alpine" locale_text="RU" dmx-bind:pagination="false"></dmx-ag-grid></div>
|
|
82
|
+
|
|
83
|
+
<h3 style="margin-top:14px;">Spanish</h3>
|
|
84
|
+
<div class="grid-wrap"><dmx-ag-grid id="g_es" dmx-bind:data="rows.value" grid_theme="ag-theme-alpine" locale_text="ES" dmx-bind:pagination="false"></dmx-ag-grid></div>
|
|
85
|
+
</section>
|
|
86
|
+
</main>
|
|
87
|
+
|
|
88
|
+
<script>
|
|
89
|
+
let dark = false;
|
|
90
|
+
function toggleDark() {
|
|
91
|
+
dark = !dark;
|
|
92
|
+
document.getElementById('dark-val').textContent = String(dark);
|
|
93
|
+
const c = TestKit.grid('g_dark');
|
|
94
|
+
if (c) c.set('dark_mode', dark);
|
|
95
|
+
}
|
|
96
|
+
</script>
|
|
97
|
+
</body>
|
|
98
|
+
</html>
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<title>03 · Editing · AG Grid Test Suite</title>
|
|
6
|
+
<link rel="stylesheet" href="./lib/test-suite.css">
|
|
7
|
+
<link rel="stylesheet" href="../node_modules/ag-grid-community/styles/ag-theme-alpine.css">
|
|
8
|
+
<link rel="stylesheet" href="../ag-theme-custom.css">
|
|
9
|
+
<link rel="stylesheet" href="../switch-toggle-slider.css">
|
|
10
|
+
|
|
11
|
+
<script src="./dmxAppConnect/dmxAppConnect.js" defer></script>
|
|
12
|
+
<script src="./lib/version-banner.js" defer></script>
|
|
13
|
+
<script src="./lib/test-helpers.js" defer></script>
|
|
14
|
+
<script src="./lib/page-template.js" defer></script>
|
|
15
|
+
<script src="../node_modules/ag-grid-community/dist/ag-grid-community.min.js" defer></script>
|
|
16
|
+
<script src="../dmx-ag-grid.js" defer></script>
|
|
17
|
+
<script src="./data/sample-data.js" defer></script>
|
|
18
|
+
</head>
|
|
19
|
+
<body is="dmx-app" id="page03">
|
|
20
|
+
|
|
21
|
+
<script>
|
|
22
|
+
window.addEventListener('DOMContentLoaded', () => {
|
|
23
|
+
TestPage.header({
|
|
24
|
+
title: '03 · Editing',
|
|
25
|
+
summary: 'Cell vs row editing, restricted editable_fields, static + dynamic select editors.'
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
</script>
|
|
29
|
+
|
|
30
|
+
<main class="test-main">
|
|
31
|
+
|
|
32
|
+
<dmx-test-data id="rows" source="employees"></dmx-test-data>
|
|
33
|
+
<dmx-event-log id="editLog"></dmx-event-log>
|
|
34
|
+
|
|
35
|
+
<section class="feature">
|
|
36
|
+
<h2>Cell editable — all fields</h2>
|
|
37
|
+
<p class="desc">
|
|
38
|
+
Double-click any cell to edit. <code>cell_data_edited</code> fires for each change with
|
|
39
|
+
<code>{ field, oldValue, newValue, rowId }</code>. Logged below.
|
|
40
|
+
</p>
|
|
41
|
+
<div class="grid-wrap">
|
|
42
|
+
<dmx-ag-grid
|
|
43
|
+
id="cellEdit"
|
|
44
|
+
dmx-bind:data="rows.value"
|
|
45
|
+
grid_theme="ag-theme-alpine"
|
|
46
|
+
dmx-bind:cell_editable="true"
|
|
47
|
+
dmx-bind:pagination="false"
|
|
48
|
+
dmx-bind:floating_filter="false"
|
|
49
|
+
dmx-on:cell_data_edited="editLog.add('cell_data_edited')">
|
|
50
|
+
</dmx-ag-grid>
|
|
51
|
+
</div>
|
|
52
|
+
</section>
|
|
53
|
+
|
|
54
|
+
<section class="feature">
|
|
55
|
+
<h2>Row editable — restricted fields</h2>
|
|
56
|
+
<p class="desc">
|
|
57
|
+
<code>row_editable=true</code> with <code>editable_fields="salary,rating,active"</code> — only those columns
|
|
58
|
+
are editable. <code>row_data_edited</code> fires once per row commit.
|
|
59
|
+
</p>
|
|
60
|
+
<div class="grid-wrap">
|
|
61
|
+
<dmx-ag-grid
|
|
62
|
+
id="rowEdit"
|
|
63
|
+
dmx-bind:data="rows.value"
|
|
64
|
+
grid_theme="ag-theme-alpine"
|
|
65
|
+
dmx-bind:row_editable="true"
|
|
66
|
+
editable_fields="salary,rating,active"
|
|
67
|
+
dmx-bind:pagination="false"
|
|
68
|
+
dmx-on:row_data_edited="editLog.add('row_data_edited')">
|
|
69
|
+
</dmx-ag-grid>
|
|
70
|
+
</div>
|
|
71
|
+
</section>
|
|
72
|
+
|
|
73
|
+
<section class="feature">
|
|
74
|
+
<h2>Select editors</h2>
|
|
75
|
+
<p class="desc">
|
|
76
|
+
<code>cstatic_select_editors</code> for <code>department</code>, <code>cdynamic_select_editors</code> for <code>active</code>.
|
|
77
|
+
Both render a dropdown editor when the cell is edited.
|
|
78
|
+
</p>
|
|
79
|
+
<div class="grid-wrap">
|
|
80
|
+
<!-- cstatic_select_editors expects { fieldName: { options: '<JSON string>' } } where
|
|
81
|
+
the JSON parses to an object whose keys become the displayed values. -->
|
|
82
|
+
<dmx-ag-grid
|
|
83
|
+
id="selectEdit"
|
|
84
|
+
dmx-bind:data="rows.value"
|
|
85
|
+
grid_theme="ag-theme-alpine"
|
|
86
|
+
dmx-bind:cell_editable="true"
|
|
87
|
+
dmx-bind:cstatic_select_editors='{"department": {"options": "{\"Engineering\":\"Engineering\",\"Sales\":\"Sales\",\"Marketing\":\"Marketing\",\"HR\":\"HR\",\"Finance\":\"Finance\"}"}}'
|
|
88
|
+
cselect_placeholder="—"
|
|
89
|
+
dmx-bind:pagination="false"
|
|
90
|
+
dmx-on:cell_data_edited="editLog.add('select_cell_edited')">
|
|
91
|
+
</dmx-ag-grid>
|
|
92
|
+
</div>
|
|
93
|
+
</section>
|
|
94
|
+
|
|
95
|
+
<section class="feature">
|
|
96
|
+
<h2>Edit log</h2>
|
|
97
|
+
<div class="kv">
|
|
98
|
+
<div class="k">events captured</div><div class="v" dmx-text="editLog.count">0</div>
|
|
99
|
+
<div class="k">last event</div><div class="v" dmx-text="editLog.last.name">—</div>
|
|
100
|
+
</div>
|
|
101
|
+
<div class="log" id="log-out"></div>
|
|
102
|
+
</section>
|
|
103
|
+
</main>
|
|
104
|
+
|
|
105
|
+
<script>
|
|
106
|
+
function renderLog() {
|
|
107
|
+
if (!window.dmx || !dmx.app) return setTimeout(renderLog, 100);
|
|
108
|
+
const log = dmx.app.get('editLog');
|
|
109
|
+
if (!log) return setTimeout(renderLog, 100);
|
|
110
|
+
const box = document.getElementById('log-out');
|
|
111
|
+
setInterval(() => {
|
|
112
|
+
const evs = log.events || [];
|
|
113
|
+
box.innerHTML = evs.map(e => '<div class="log-entry">' + e.at + ' — ' + e.name + '</div>').join('');
|
|
114
|
+
}, 500);
|
|
115
|
+
}
|
|
116
|
+
renderLog();
|
|
117
|
+
</script>
|
|
118
|
+
</body>
|
|
119
|
+
</html>
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<title>04 · Selection & Row Events</title>
|
|
6
|
+
<link rel="stylesheet" href="./lib/test-suite.css">
|
|
7
|
+
<link rel="stylesheet" href="../node_modules/ag-grid-community/styles/ag-theme-alpine.css">
|
|
8
|
+
<link rel="stylesheet" href="../ag-theme-custom.css">
|
|
9
|
+
<link rel="stylesheet" href="../switch-toggle-slider.css">
|
|
10
|
+
<script src="./dmxAppConnect/dmxAppConnect.js" defer></script>
|
|
11
|
+
<script src="./lib/version-banner.js" defer></script>
|
|
12
|
+
<script src="./lib/test-helpers.js" defer></script>
|
|
13
|
+
<script src="./lib/page-template.js" defer></script>
|
|
14
|
+
<script src="../node_modules/ag-grid-community/dist/ag-grid-community.min.js" defer></script>
|
|
15
|
+
<script src="../dmx-ag-grid.js" defer></script>
|
|
16
|
+
<script src="./data/sample-data.js" defer></script>
|
|
17
|
+
</head>
|
|
18
|
+
<body is="dmx-app" id="page04">
|
|
19
|
+
|
|
20
|
+
<script>
|
|
21
|
+
window.addEventListener('DOMContentLoaded', () => {
|
|
22
|
+
TestPage.header({
|
|
23
|
+
title: '04 · Selection & Row Events',
|
|
24
|
+
summary: 'Single vs multi-row selection, row checkbox events, status toggle, click + double-click hooks.'
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
</script>
|
|
28
|
+
|
|
29
|
+
<main class="test-main">
|
|
30
|
+
<dmx-test-data id="rows" source="employees"></dmx-test-data>
|
|
31
|
+
<dmx-event-log id="evLog"></dmx-event-log>
|
|
32
|
+
|
|
33
|
+
<section class="feature">
|
|
34
|
+
<h2>Multi-row selection with checkbox events</h2>
|
|
35
|
+
<p class="desc">
|
|
36
|
+
<code>row_selection="multiRow"</code>, <code>row_checkbox_event=true</code>, <code>row_status_event=true</code>.
|
|
37
|
+
Selected rows are exposed via <code>selectedRows</code>.
|
|
38
|
+
</p>
|
|
39
|
+
<div class="grid-wrap">
|
|
40
|
+
<dmx-ag-grid
|
|
41
|
+
id="selGrid"
|
|
42
|
+
dmx-bind:data="rows.value"
|
|
43
|
+
grid_theme="ag-theme-alpine"
|
|
44
|
+
row_selection="multiRow"
|
|
45
|
+
dmx-bind:row_checkbox_event="true"
|
|
46
|
+
dmx-bind:row_status_event="true"
|
|
47
|
+
dmx-bind:row_click_event="true"
|
|
48
|
+
dmx-bind:row_double_click_event="true"
|
|
49
|
+
dmx-bind:pagination="false"
|
|
50
|
+
dmx-on:row_clicked="evLog.add('row_clicked')"
|
|
51
|
+
dmx-on:row_double_clicked="evLog.add('row_double_clicked')"
|
|
52
|
+
dmx-on:row_checkbox_checked="evLog.add('row_checkbox_checked')"
|
|
53
|
+
dmx-on:row_checkbox_unchecked="evLog.add('row_checkbox_unchecked')"
|
|
54
|
+
dmx-on:row_status_enabled="evLog.add('row_status_enabled')"
|
|
55
|
+
dmx-on:row_status_disabled="evLog.add('row_status_disabled')">
|
|
56
|
+
</dmx-ag-grid>
|
|
57
|
+
</div>
|
|
58
|
+
|
|
59
|
+
<div class="controls">
|
|
60
|
+
<button class="primary" onclick="TestKit.callMethod('selGrid','getSelectedRows')">getSelectedRows()</button>
|
|
61
|
+
<button onclick="dumpSelected()">log selectedRows binding</button>
|
|
62
|
+
</div>
|
|
63
|
+
|
|
64
|
+
<div class="kv">
|
|
65
|
+
<div class="k">selectedRows.length</div>
|
|
66
|
+
<div class="v" dmx-text="selGrid.selectedRows.length">0</div>
|
|
67
|
+
<div class="k">last event</div>
|
|
68
|
+
<div class="v" dmx-text="evLog.last.name">—</div>
|
|
69
|
+
</div>
|
|
70
|
+
</section>
|
|
71
|
+
|
|
72
|
+
<section class="feature">
|
|
73
|
+
<h2>Single-row selection</h2>
|
|
74
|
+
<p class="desc"><code>row_selection="singleRow"</code> — clicking a row replaces selection.</p>
|
|
75
|
+
<div class="grid-wrap">
|
|
76
|
+
<dmx-ag-grid id="singleSel" dmx-bind:data="rows.value" grid_theme="ag-theme-alpine" row_selection="singleRow" dmx-bind:pagination="false"></dmx-ag-grid>
|
|
77
|
+
</div>
|
|
78
|
+
</section>
|
|
79
|
+
|
|
80
|
+
<section class="feature">
|
|
81
|
+
<h2>Event log</h2>
|
|
82
|
+
<div class="log" id="log-out"></div>
|
|
83
|
+
</section>
|
|
84
|
+
</main>
|
|
85
|
+
|
|
86
|
+
<script>
|
|
87
|
+
function dumpSelected() {
|
|
88
|
+
const c = TestKit.grid('selGrid');
|
|
89
|
+
console.log('selectedRows', c && c.get('selectedRows'));
|
|
90
|
+
}
|
|
91
|
+
(function pollLog() {
|
|
92
|
+
if (!window.dmx || !dmx.app) return setTimeout(pollLog, 100);
|
|
93
|
+
const log = dmx.app.get('evLog');
|
|
94
|
+
if (!log) return setTimeout(pollLog, 100);
|
|
95
|
+
setInterval(() => {
|
|
96
|
+
const evs = log.events || [];
|
|
97
|
+
document.getElementById('log-out').innerHTML =
|
|
98
|
+
evs.slice(0, 30).map(e => '<div class="log-entry">' + e.at + ' — ' + e.name + '</div>').join('');
|
|
99
|
+
}, 400);
|
|
100
|
+
})();
|
|
101
|
+
</script>
|
|
102
|
+
</body>
|
|
103
|
+
</html>
|