Skip to content

Commit 18144c1

Browse files
authored
[DataGrid] Add UseMenuService parameter to override menu behavior (#3862)
* Initial work * Restore IssueTester and undo other issue trials * Fix multiple menus being shown because header button breaks through overlay
1 parent c1dc136 commit 18144c1

File tree

8 files changed

+31
-8
lines changed

8 files changed

+31
-8
lines changed

examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1966,6 +1966,13 @@
19661966
If true, enables the new style of header cell that includes a button to display all column options through a menu.
19671967
</summary>
19681968
</member>
1969+
<member name="P:Microsoft.FluentUI.AspNetCore.Components.FluentDataGrid`1.UseMenuService">
1970+
<summary>
1971+
Use IMenuService to create the menu, if this service was injected.
1972+
This value must be defined before the component is rendered (you can't change it during the component lifecycle).
1973+
Default, true.
1974+
</summary>
1975+
</member>
19691976
<member name="P:Microsoft.FluentUI.AspNetCore.Components.FluentDataGrid`1.ItemKey">
19701977
<summary>
19711978
Optionally defines a value for @key on each rendered row. Typically this should be used to specify a

examples/Demo/Shared/Pages/DataGrid/DataGridPage.razor

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
<h2 id="sorting">Sorting</h2>
5959
<p>
6060
The DataGrid supports sorting by clicking on the column headers. The default sort direction is ascending. Clicking on the same column header again will toggle the sort direction.
61-
A sort can be removed by right clicking on the header column (with exception of the default sort).
61+
A sort can be removed by right clicking (or by pressing Shift+R) on the header column (with exception of the default sort).
6262
</p>
6363

6464
<h2 id="styling">Row size</h2>

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,14 @@
1818
</FluentRadioGroup>
1919
<FluentSpacer Width="25" />
2020
<FluentCheckbox @bind-Value="@_showActionsMenu" Label="Use menu for column actions" />
21+
<FluentCheckbox @bind-Value="@_useMenuService" Label="Use service for rendering menu" Disabled="!_showActionsMenu" />
2122
</FluentToolbar>
2223
<div style="height: 400px; overflow-x:auto; display:flex;">
2324
<FluentDataGrid Items="@FilteredItems"
2425
ResizableColumns=true
2526
ResizeType="@_resizeType"
2627
HeaderCellAsButtonWithMenu="_showActionsMenu"
28+
UseMenuService="_useMenuService"
2729
Pagination="@pagination"
2830
TGridItem="Country"
2931
OnRowFocus="HandleRowFocus"
@@ -75,6 +77,7 @@
7577
string nameFilter = string.Empty;
7678
DataGridResizeType? _resizeType = null;
7779
bool _showActionsMenu;
80+
bool _useMenuService = true;
7881

7982
GridSort<Country> rankSort = GridSort<Country>
8083
.ByDescending(x => x.Medals.Gold)

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
{
3030
string? tooltip = Tooltip ? (HeaderTooltip ?? Title) : null;
3131

32-
<FluentKeyCode Only="new[] { KeyCode.Ctrl, KeyCode.Enter }" OnKeyDown="HandleKeyDown" class="keycapture" style="width: 100%;" StopPropagation="true" @oncontextmenu="@(() => Grid.RemoveSortByColumnAsync(this))">
32+
<FluentKeyCode Only="@(new[] { KeyCode.KeyR })" OnKeyDown="HandleKeyDown" class="keycapture" style="width: 100%;" StopPropagation="true" @oncontextmenu="@(() => Grid.RemoveSortByColumnAsync(this))">
3333

3434
@if (AnyColumnActionEnabled)
3535
{
@@ -63,7 +63,7 @@
6363
</div>
6464
</div>
6565
}
66-
<FluentMenu Anchor="@_columnId" @bind-Open="@_isMenuOpen" HorizontalViewportLock="false" HorizontalPosition="HorizontalPosition.End">
66+
<FluentMenu @ref="@_menu" UseMenuService="@Grid.UseMenuService" Anchor="@_columnId" @bind-Open="@_isMenuOpen" HorizontalViewportLock="false" HorizontalPosition="HorizontalPosition.End">
6767
@if (Sortable.HasValue ? Sortable.Value : IsSortableByDefault())
6868
{
6969
<FluentMenuItem OnClick="@(async () => await Grid.SortByColumnAsync(this))" @onkeydown="HandleSortMenuKeyDownAsync">

src/Core/Components/DataGrid/Columns/ColumnBase.razor.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ public abstract partial class ColumnBase<TGridItem>
1919
private bool _isMenuOpen;
2020
private static readonly string[] KEYBOARD_MENU_SELECT_KEYS = ["Enter", "NumpadEnter"];
2121
private readonly string _columnId = Identifier.NewId();
22+
private FluentMenu? _menu;
2223

2324
[CascadingParameter]
2425
internal InternalGridContext<TGridItem> InternalGridContext { get; set; } = default!;
@@ -248,7 +249,7 @@ protected internal virtual Task OnCellKeyDownAsync(FluentDataGridCell<TGridItem>
248249

249250
protected void HandleKeyDown(FluentKeyCodeEventArgs e)
250251
{
251-
if (e.CtrlKey && e.Key == KeyCode.Enter)
252+
if (e.ShiftKey && e.Key == KeyCode.KeyR)
252253
{
253254
Grid.RemoveSortByColumnAsync(this);
254255
}

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ public partial class FluentDataGrid<TGridItem> : FluentComponentBase, IHandleEve
2424
private const string JAVASCRIPT_FILE = "./_content/Microsoft.FluentUI.AspNetCore.Components/Components/DataGrid/FluentDataGrid.razor.js";
2525
public const string EMPTY_CONTENT_ROW_CLASS = "empty-content-row";
2626
public const string LOADING_CONTENT_ROW_CLASS = "loading-content-row";
27+
public List<FluentMenu> _menuReferences = [];
2728

2829
/// <summary />
2930
[Inject]
@@ -148,6 +149,14 @@ public partial class FluentDataGrid<TGridItem> : FluentComponentBase, IHandleEve
148149
[Parameter]
149150
public bool HeaderCellAsButtonWithMenu { get; set; }
150151

152+
/// <summary>
153+
/// Use IMenuService to create the menu, if this service was injected.
154+
/// This value must be defined before the component is rendered (you can't change it during the component lifecycle).
155+
/// Default, true.
156+
/// </summary>
157+
[Parameter]
158+
public bool UseMenuService { get; set; } = true;
159+
151160
/// <summary>
152161
/// Optionally defines a value for @key on each rendered row. Typically this should be used to specify a
153162
/// unique identifier, such as a primary key value, for each data item.

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

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ export function init(gridElement, autoFocus) {
3232
}
3333
}
3434
const keyDownHandler = event => {
35+
if (document.activeElement.tagName.toLowerCase() != 'table' && document.activeElement.tagName.toLowerCase() != 'td' && document.activeElement.tagName.toLowerCase() != 'th') {
36+
return;
37+
}
3538
const columnOptionsElement = gridElement?.querySelector('.col-options');
3639
if (columnOptionsElement) {
3740
if (event.key === "Escape") {
@@ -64,7 +67,7 @@ export function init(gridElement, autoFocus) {
6467
}
6568

6669
// check if start is a child of gridElement
67-
if (start !== null && (gridElement.contains(start) || gridElement === start) && document.activeElement === start && document.activeElement.tagName.toLowerCase() !== 'fluent-text-field') {
70+
if (start !== null && (gridElement.contains(start) || gridElement === start) && document.activeElement === start && document.activeElement.tagName.toLowerCase() !== 'fluent-text-field' && document.activeElement.tagName.toLowerCase() !== 'fluent-menu-item') {
6871
const idx = start.cellIndex;
6972

7073
if (event.key === "ArrowUp") {
@@ -124,13 +127,13 @@ export function init(gridElement, autoFocus) {
124127

125128
document.body.addEventListener('click', bodyClickHandler);
126129
document.body.addEventListener('mousedown', bodyClickHandler); // Otherwise it seems strange that it doesn't go away until you release the mouse button
127-
document.body.addEventListener('keydown', keyDownHandler);
130+
gridElement.addEventListener('keydown', keyDownHandler);
128131

129132
return {
130133
stop: () => {
131134
document.body.removeEventListener('click', bodyClickHandler);
132135
document.body.removeEventListener('mousedown', bodyClickHandler);
133-
document.body.removeEventListener('keydown', keyDownHandler);
136+
gridElement.removeEventListener('keydown', keyDownHandler);
134137
delete grids[gridElement];
135138
}
136139
};

src/Core/Components/DataGrid/FluentDataGridCell.razor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ public partial class FluentDataGridCell<TGridItem> : FluentComponentBase
7979
.AddStyle("height", $"{(int)Grid.RowSize}px", () => !Grid.EffectiveLoadingValue && !Grid.Virtualize && !Grid.MultiLine && (Grid.Items is not null || Grid.ItemsProvider is not null))
8080
.AddStyle("height", "100%", Grid.MultiLine)
8181
.AddStyle("min-height", "44px", Owner.RowType != DataGridRowType.Default)
82-
.AddStyle("z-index", ZIndex.DataGridHeaderPopup.ToString(), CellType == DataGridCellType.ColumnHeader && Grid._columns.Count > 0)
82+
.AddStyle("z-index", ZIndex.DataGridHeaderPopup.ToString(), CellType == DataGridCellType.ColumnHeader && Grid._columns.Count > 0 && Grid.UseMenuService)
8383
.AddStyle(Owner.Style)
8484
.Build();
8585

0 commit comments

Comments
 (0)