Skip to content

Commit 91381a1

Browse files
authored
Users/vnbaaij/improve datagrid script (#4500)
* 1. Cleanup Logic: Updated the stop function in init to explicitly abort and remove the resizeController for the grid instance. 2. Dynamic AbortSignal: Updated enableColumnResizing to: • Detect if a grid already has a resizeController and abort it before creating a new one (e.g., when columns are re-evaluated). 1. Create a localController if no external signal is provided from Blazor. 2. Use an effectiveSignal for all resizing event listeners. 3. Registry Persistence: Modified the grid registration logic to store the resizeController so it can be managed during re-initialization or disposal. These changes ensure that whenever column resizing is re-enabled (which happens in Blazor when columns change), the old JS listeners are properly cleaned up via the AbortController. * - Improve key handling - Port v5 script improvement * Update some samples and refine DG script
1 parent 40be864 commit 91381a1

5 files changed

Lines changed: 67 additions & 32 deletions

File tree

examples/Demo/Shared/Pages/DataGrid/Examples/DataGridCustomComparer.razor

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@
44
{
55
<style>
66
:root {
7-
--datagrid-hover-color: lightyellow;
8-
7+
--datagrid-hover-color: lightyellow;
98
}
109
1110
.fluent-data-grid {
12-
--fluent-data-grid-resize-handle-color: var(--neutral-stroke-rest) !important;
13-
}
11+
--fluent-data-grid-resize-handle-color: var(--neutral-stroke-rest) !important;
12+
--fluent-data-grid-header-opacity: 1 !important;
13+
}
1414
</style>
1515

1616
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
/* Ensure all the flags are the same size, and centered */
1+
/* Ensure all the flags are the same size, and centered */
22
.flag {
33
height: 1rem;
44
margin: auto;
55
border: 1px solid var(--neutral-layer-3);
6-
}
6+
}

examples/Demo/Shared/Pages/DataGrid/Examples/DataGridHierarchical.razor

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
99
.fluent-data-grid {
1010
--fluent-data-grid-resize-handle-color: var(--neutral-stroke-rest) !important;
11+
--fluent-data-grid-resize-handle-opacity: 1 !important;
1112
}
1213
1314
.flag {

src/Core/Components/DataGrid/Columns/ColumnResizeOptions.razor

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77
<FluentLabel>@Grid.ColumnResizeLabels.DiscreteLabel</FluentLabel>
88

99
<FluentSpacer />
10-
<FluentButton OnClick="@HandleShrinkAsync" IconStart="@(new CoreIcons.Regular.Size20.Subtract())" aria-label="@(Grid.ColumnResizeLabels.ShrinkAriaLabel)" />
11-
<FluentButton OnClick="@HandleGrowAsync" IconStart="@(new CoreIcons.Regular.Size20.Add())" aria-label="@(Grid.ColumnResizeLabels.GrowAriaLabel)" />
12-
<FluentButton OnClick="@HandleResetAsync" IconStart="@(new CoreIcons.Regular.Size20.ArrowReset())" aria-label="@(Grid.ColumnResizeLabels.ResetAriaLabel)" />
10+
<FluentButton OnClick="@HandleShrinkAsync" IconStart="@(new CoreIcons.Regular.Size20.Subtract())" aria-label="@(Grid.ColumnResizeLabels.ShrinkAriaLabel)" tabindex="0" Autofocus="true"/>
11+
<FluentButton OnClick="@HandleGrowAsync" IconStart="@(new CoreIcons.Regular.Size20.Add())" aria-label="@(Grid.ColumnResizeLabels.GrowAriaLabel)" tabindex="0" />
12+
<FluentButton OnClick="@HandleResetAsync" IconStart="@(new CoreIcons.Regular.Size20.ArrowReset())" aria-label="@(Grid.ColumnResizeLabels.ResetAriaLabel)" tabindex="0 " />
1313
}
1414
else
1515
{

src/Core/Components/DataGrid/FluentDataGrid.razor.js

Lines changed: 57 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,20 @@ export function init(gridElement, autoFocus) {
2626
gridElement.dispatchEvent(new CustomEvent('closecolumnresize', { bubbles: true }));
2727
}
2828
};
29+
const bodyKeyDownHandler = event => {
30+
if (event.key === "Escape") {
31+
const columnOptionsElement = gridElement?.querySelector('.col-options');
32+
if (columnOptionsElement && columnOptionsElement.contains(event.target)) {
33+
gridElement.dispatchEvent(new CustomEvent('closecolumnoptions', { bubbles: true }));
34+
gridElement.focus();
35+
}
36+
const columnResizeElement = gridElement?.querySelector('.col-resize');
37+
if (columnResizeElement) {
38+
gridElement.dispatchEvent(new CustomEvent('closecolumnresize', { bubbles: true }));
39+
gridElement.focus();
40+
}
41+
}
42+
};
2943
const keyboardNavigation = (sibling) => {
3044
if (sibling !== null) {
3145
start.focus();
@@ -38,21 +52,15 @@ export function init(gridElement, autoFocus) {
3852
if (columnOptionsElement && columnOptionsElement.contains(event.target)) {
3953
if (event.key === "ArrowRight" || event.key === "ArrowLeft" || event.key === "ArrowDown" || event.key === "ArrowUp") {
4054
event.stopPropagation();
41-
}
42-
if (event.key === "Escape") {
43-
gridElement.dispatchEvent(new CustomEvent('closecolumnoptions', { bubbles: true }));
44-
gridElement.focus();
55+
return;
4556
}
4657
}
4758

4859
const columnResizeElement = gridElement?.querySelector('.col-resize');
4960
if (columnResizeElement && columnResizeElement.contains(event.target)) {
5061
if (event.key === "ArrowRight" || event.key === "ArrowLeft" || event.key === "ArrowDown" || event.key === "ArrowUp") {
5162
event.stopPropagation();
52-
}
53-
if (event.key === "Escape") {
54-
gridElement.dispatchEvent(new CustomEvent('closecolumnresize', { bubbles: true }));
55-
gridElement.focus();
63+
return;
5664
}
5765
}
5866

@@ -123,6 +131,7 @@ export function init(gridElement, autoFocus) {
123131

124132
document.body.addEventListener('click', bodyClickHandler, { signal });
125133
document.body.addEventListener('mousedown', bodyClickHandler, { signal }); // Otherwise it seems strange that it doesn't go away until you release the mouse button
134+
document.body.addEventListener('keydown', bodyKeyDownHandler, { signal });
126135
gridElement.addEventListener('keydown', keyDownHandler, { signal });
127136

128137
return {
@@ -131,6 +140,10 @@ export function init(gridElement, autoFocus) {
131140

132141
const index = grids.findIndex(grid => grid.id === gridElement.id);
133142
if (index > -1) {
143+
const grid = grids[index];
144+
if (grid.resizeController) {
145+
grid.resizeController.abort();
146+
}
134147
grids.splice(index, 1);
135148
}
136149
}
@@ -167,6 +180,16 @@ export function enableColumnResizing(gridElement, resizeColumnOnAllRows = true,
167180
return;
168181
}
169182

183+
const id = gridElement.id;
184+
let grid = grids.find(g => g.id === id);
185+
186+
if (grid?.resizeController) {
187+
grid.resizeController.abort();
188+
}
189+
190+
const localController = signal ? null : new AbortController();
191+
const effectiveSignal = signal ?? localController.signal;
192+
170193
const isGrid = gridElement.classList.contains('grid')
171194

172195
let tableHeight = gridElement.offsetHeight;
@@ -186,7 +209,7 @@ export function enableColumnResizing(gridElement, resizeColumnOnAllRows = true,
186209
if (!resizeColumnOnAllRows) {
187210
// Only use the header height when resizeColumnOnAllRows is false
188211
// Use the first header's height if available
189-
resizeHandleHeight = headers.length > 0 ? (headers[0].offsetHeight - 14 ): 32; // fallback to 32px if no headers
212+
resizeHandleHeight = headers.length > 0 ? (headers[0].offsetHeight - 14) : 32; // fallback to 32px if no headers
190213
}
191214

192215
headers.forEach((header) => {
@@ -196,7 +219,7 @@ export function enableColumnResizing(gridElement, resizeColumnOnAllRows = true,
196219
});
197220

198221
// remove any previously created divs
199-
const resizedivs = header.querySelectorAll(".actual-resize-handle");
222+
const resizedivs = header.querySelectorAll(".actual-resize-handle");
200223
resizedivs.forEach(div => div.remove());
201224

202225
// Get the top of the first resize-handle
@@ -205,7 +228,7 @@ export function enableColumnResizing(gridElement, resizeColumnOnAllRows = true,
205228
// add a new resize div
206229
const div = createDiv(resizeHandleHeight, resizeTop);
207230
header.appendChild(div);
208-
setListeners(div, signal);
231+
setListeners(div, effectiveSignal);
209232
});
210233

211234
let initialWidths;
@@ -219,13 +242,20 @@ export function enableColumnResizing(gridElement, resizeColumnOnAllRows = true,
219242
}
220243
}
221244

222-
const id = gridElement.id;
223-
if (!grids.find(grid => grid.id === id)) {
245+
if (!grid) {
224246
grids.push({
225247
id,
226248
columns,
227249
initialWidths,
250+
resizeController: signal ? undefined : localController,
228251
});
252+
} else {
253+
const columnsChanged = grid.columns.length !== columns.length;
254+
grid.columns = columns;
255+
if (columnsChanged) {
256+
grid.initialWidths = initialWidths;
257+
}
258+
grid.resizeController = signal ? undefined : localController;
229259
}
230260

231261
function setListeners(div, signal) {
@@ -334,19 +364,23 @@ export function resetColumnWidths(gridElement) {
334364
return;
335365
}
336366

337-
const columnsWidths = grid.initialWidths.split(' ');
338-
339-
grid.columns.forEach((column, index) => {
340-
if (isGrid) {
341-
column.size = columnsWidths[index];
342-
} else {
343-
column.header.style.width = columnsWidths[index];
344-
}
345-
});
346-
347367
if (isGrid) {
348368
gridElement.style.gridTemplateColumns = grid.initialWidths;
369+
370+
// Force browser to recalculate so we can get accurate computed widths
371+
const resolvedWidths = window.getComputedStyle(gridElement).gridTemplateColumns.split(' ');
372+
373+
grid.columns.forEach((column, index) => {
374+
column.size = resolvedWidths[index];
375+
});
376+
} else {
377+
const columnsWidths = grid.initialWidths.split(' ');
378+
grid.columns.forEach((column, index) => {
379+
column.size = columnsWidths[index];
380+
column.header.style.width = column.size;
381+
});
349382
}
383+
350384
gridElement.dispatchEvent(
351385
new CustomEvent('closecolumnresize', { bubbles: true })
352386
);

0 commit comments

Comments
 (0)