Skip to content

Commit b205e0a

Browse files
github-actions[bot]dimodiikoevska
authored
Merge kb-grid-drag-hierarchy-2696 into production (#2704)
* kb(Grid): Add KB for drag-and-drop in Grid hierarchy * Update knowledge-base/grid-drag-drop-rows-hierarchy.md Co-authored-by: Iva Stefanova Koevska-Atanasova <koevska@progress.com> * Update knowledge-base/grid-drag-drop-rows-hierarchy.md * Polish list of links --------- Co-authored-by: Dimo Dimov <961014+dimodi@users.noreply.github.com> Co-authored-by: Iva Stefanova Koevska-Atanasova <koevska@progress.com>
1 parent 833ce9e commit b205e0a

File tree

3 files changed

+268
-9
lines changed

3 files changed

+268
-9
lines changed

components/grid/hierarchy.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,7 @@ The following articles and sample projects can be helpful when implementing hier
125125

126126
## See Also
127127

128-
* [Live Demo: Grid Hierarchy](https://demos.telerik.com/blazor-ui/grid/hierarchy)
129-
* [KB: Customize Hierarchy Expand Column in Blazor Grid](slug://grid-kb-customize-hierarchy-expand-column-blazor-grid)
130-
* [Blazor Grid](slug://grid-overview)
131-
132-
128+
* [Live Demo: Grid Hierarchy](https://demos.telerik.com/blazor-ui/grid/hierarchy)
129+
* [Customize Hierarchy Expand Column in Blazor Grid](slug://grid-kb-customize-hierarchy-expand-column-blazor-grid)
130+
* [Drag and Drop Rows in Grid Hierarchy](slug://grid-kb-drag-drop-rows-hierarchy)
131+
* [Blazor Grid](slug://grid-overview)

components/grid/row-drag-drop.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -132,14 +132,14 @@ This section contains the following examples:
132132

133133
### Drag and Drop a Row between Grids
134134

135-
When you drag and drop items from one Grid to another, the `OnRowDrop` event fires for both Grid instances, so you can update their data sources. All Grid instances must be bound to the same model type. It is also possible to [bind the Grids to different models, but they must be derived from the same interface](slug://grid-kb-drag-drop-different-models).
135+
When you drag and drop items from one Grid to another, the `OnRowDrop` event fires for the source Grid instance and provides information about the destination Grid. Thus you can update the data sources of both Grids. The Grid instances must be bound to the same model type. It is also possible to [bind the Grids to different models, but they must be derived from the same interface](slug://grid-kb-drag-drop-different-models).
136136

137137
The target drop area in the Grid is the `<table>` element. Users cannot drop items in the empty space below the last table row and this includes the `NoDataTemplate` too. There are two ways to prevent possible confusion and enhance the UX:
138138

139139
* Do not set a Grid `Height`, so that there is no empty space below the last table row.
140140
* Define a [`NoDataTemplate`](slug://grid-templates-no-data), which fills the Grid data area.
141141

142-
The following example demonstrates both these options:
142+
The following example demonstrates both these options. You can also check how to [drag and drop rows in a Grid hierarchy](slug://grid-kb-drag-drop-rows-hierarchy).
143143

144144
>caption Drag and drop items between Grids
145145
@@ -1769,7 +1769,6 @@ List on known limitations for the Grid Drag and Drop features:
17691769
## See Also
17701770

17711771
* [Live Demo: Grid Drag and Drop](https://demos.telerik.com/blazor-ui/grid/drag-drop)
1772+
* [Drag and Drop Rows in Grid Hierarchy](slug://grid-kb-drag-drop-rows-hierarchy)
17721773
* [Drag and Drop between Different Parent Components](slug://grid-kb-drag-drop-in-different-components)
17731774
* [Grid API Reference](/blazor-ui/api/Telerik.Blazor.Components.TelerikGrid-1)
1774-
* [Blazor Grid](slug://grid-overview)
1775-
Lines changed: 261 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,261 @@
1+
---
2+
title: Drag and Drop Grid Rows in Hierarchy
3+
description: Learn how to implement and set up drag-and-drop in hierarchical Blazor Grid scenarios. Enable or disable dragging and dropping in specific Grid instances in the hierarchy.
4+
type: how-to
5+
page_title: How to Drag and Drop Grid Rows in Hierarchy
6+
slug: grid-kb-drag-drop-rows-hierarchy
7+
tags: blazor, grid, hierarchy, drag and drop
8+
ticketid: 1675157
9+
res_type: kb
10+
---
11+
12+
## Environment
13+
14+
<table>
15+
<tbody>
16+
<tr>
17+
<td>Product</td>
18+
<td>
19+
Grid for Blazor
20+
</td>
21+
</tr>
22+
</tbody>
23+
</table>
24+
25+
## Description
26+
27+
This KB answers the following questions:
28+
29+
* How to configure drag-and-drop in a hierarchy of Telerik Grids for Blazor?
30+
* How to drag detail rows from a child Grid and drop them on the master (parent) Grid?
31+
* How to prevent users from dragging and dropping master Grid rows to detail (child) Grids?
32+
33+
## Solution
34+
35+
1. Configure the [Grid hierarchy](slug://components/grid/features/hierarchy) with a `<DetailTemplate>`.
36+
1. [Set `RowDraggable="true"` and handle the `OnRowDrop` event](slug://grid-drag-drop-overview) for the master or detail Grids.
37+
1. [Set unique `@ref` attributes to all detail Grid instances](slug://common-kb-dynamic-refs).
38+
1. [Set unique `@key` attributes to all detail Grid instances](slug://grid-kb-using-components-in-templates).
39+
1. (optional) Disable dragging from certain Grids. Use custom CSS to hide specific drag columns. The example below shows how to do this separately for each Grid instance in the hierarchy.
40+
1. (optional) Disable dropping to certain Grid instances. Use logic in the `OnRowDrop` event handlers. The example below prevents dragging and dropping of master rows to the detail Grids.
41+
42+
>caption Drag and drop rows in Grid hierarchy
43+
44+
````RAZOR
45+
<TelerikGrid @ref="@MasterGridRef"
46+
Data="@MasterGridData"
47+
TItem="@GridModel"
48+
Class="@( MasterGridDrag ? string.Empty : "no-drag-column" )"
49+
RowDraggable="true"
50+
OnRowDrop="@OnMasterGridDrop"
51+
OnStateInit="@OnMasterGridInit">
52+
<GridSettings>
53+
<GridRowDraggableSettings DragClueField="@nameof(GridModel.Text)" />
54+
</GridSettings>
55+
<GridToolBarTemplate>
56+
<label class="grid-label"><TelerikCheckBox @bind-Value="@MasterGridDrag" /> Allow Dragging</label>
57+
<span class="k-separator"></span>
58+
<label class="grid-label"><TelerikCheckBox @bind-Value="@MasterGridDrop" /> Allow Dropping</label>
59+
</GridToolBarTemplate>
60+
<GridColumns>
61+
<GridColumn Field="@(nameof(GridModel.Id))" Width="120px" />
62+
<GridColumn Field="@(nameof(GridModel.ParentId))" Width="120px" />
63+
<GridColumn Field="@(nameof(GridModel.Text))" />
64+
</GridColumns>
65+
<DetailTemplate>
66+
@{
67+
var masterItem = (GridModel)context;
68+
if (!DetailGridConfig.ContainsKey(masterItem.Id))
69+
{
70+
DetailGridConfig.Add(masterItem.Id, new() { GridRef = new TelerikGrid<GridModel>() });
71+
}
72+
}
73+
<TelerikGrid @key="@( $"grid-detail-key-{masterItem.Id}" )"
74+
@ref="@DetailGridConfig[masterItem.Id].GridRef"
75+
Data="@DetailGridData.Where(x => x.ParentId == masterItem.Id)"
76+
TItem="@GridModel"
77+
Class="@( DetailGridConfig[masterItem.Id].AllowDrag ? string.Empty : "no-drag-column" )"
78+
RowDraggable="true"
79+
OnRowDrop="@OnDetailGridDrop">
80+
<GridSettings>
81+
<GridRowDraggableSettings DragClueField="@nameof(GridModel.Text)"></GridRowDraggableSettings>
82+
</GridSettings>
83+
<GridToolBarTemplate>
84+
<label class="grid-label">
85+
<TelerikCheckBox Value="@DetailGridConfig[masterItem.Id].AllowDrag"
86+
ValueChanged="@( (bool newValue) => DetailGridDragChanged(newValue, masterItem.Id) )" />
87+
Allow Dragging
88+
</label>
89+
<span class="k-separator"></span>
90+
<label class="grid-label">
91+
<TelerikCheckBox Value="@DetailGridConfig[masterItem.Id].AllowDrop"
92+
ValueChanged="@( (bool newValue) => DetailGridDropChanged(newValue, masterItem.Id) )" />
93+
Allow Dropping
94+
</label>
95+
</GridToolBarTemplate>
96+
<GridColumns>
97+
<GridColumn Field="@(nameof(GridModel.Id))" Width="120px" />
98+
<GridColumn Field="@(nameof(GridModel.ParentId))" Width="120px" />
99+
<GridColumn Field="@(nameof(GridModel.Text))" />
100+
</GridColumns>
101+
</TelerikGrid>
102+
</DetailTemplate>
103+
</TelerikGrid>
104+
105+
<style>
106+
.grid-label {
107+
display: inline-flex;
108+
gap: .3em;
109+
}
110+
111+
/* master header area */
112+
.no-drag-column > div > .k-grid-header .k-drag-col {
113+
width: 0;
114+
}
115+
116+
.no-drag-column > div > .k-grid-header .k-drag-cell + th {
117+
border-left-width: 0;
118+
}
119+
120+
.no-drag-column > div > .k-grid-header .k-drag-cell * {
121+
display: none;
122+
}
123+
124+
/* detail data area */
125+
.no-drag-column > div > .k-grid-container > .k-grid-content > div > div > table > colgroup > .k-drag-col {
126+
width: 0;
127+
}
128+
129+
.no-drag-column > div > .k-grid-container > .k-grid-content > div > div > table > tbody > tr > .k-drag-cell + td,
130+
.no-drag-column > div > .k-grid-container > .k-grid-content > div > div > table > tbody > tr > .k-hierarchy-cell {
131+
border-left-width: 0;
132+
}
133+
134+
.no-drag-column > div > .k-grid-container > .k-grid-content > div > div > table > tbody > tr > .k-drag-cell * {
135+
display: none;
136+
}
137+
</style>
138+
139+
@code {
140+
private TelerikGrid<GridModel>? MasterGridRef { get; set; }
141+
private Dictionary<int, GridDragDropDescriptor> DetailGridConfig { get; set; } = new();
142+
143+
private bool MasterGridDrag { get; set; } = true;
144+
private bool MasterGridDrop { get; set; } = true;
145+
146+
private void OnMasterGridDrop(GridRowDropEventArgs<GridModel> args)
147+
{
148+
if (!MasterGridDrop || args.DestinationGrid != MasterGridRef)
149+
{
150+
return;
151+
}
152+
153+
MasterGridData.Remove(args.Item);
154+
InsertGridItem(args);
155+
}
156+
157+
private void OnDetailGridDrop(GridRowDropEventArgs<GridModel> args)
158+
{
159+
if (args.DestinationGrid != MasterGridRef)
160+
{
161+
int masterId = DetailGridConfig.First(x => x.Value.GridRef == args.DestinationGrid).Key;
162+
163+
if (!DetailGridConfig[masterId].AllowDrop)
164+
{
165+
return;
166+
}
167+
}
168+
else if (!MasterGridDrop)
169+
{
170+
return;
171+
}
172+
173+
DetailGridData.Remove(args.Item);
174+
InsertGridItem(args);
175+
}
176+
177+
private void InsertGridItem(GridRowDropEventArgs<GridModel> args)
178+
{
179+
List<GridModel> destinationGridData = new();
180+
int? newParentId = null;
181+
182+
if (args.DestinationGrid == MasterGridRef)
183+
{
184+
destinationGridData = MasterGridData;
185+
}
186+
else
187+
{
188+
destinationGridData = DetailGridData;
189+
newParentId = DetailGridConfig.First(x => x.Value.GridRef == args.DestinationGrid).Key;
190+
}
191+
192+
var destinationIndex = 0;
193+
194+
if (args.DestinationItem != null)
195+
{
196+
destinationIndex = destinationGridData.IndexOf(args.DestinationItem);
197+
if (args.DropPosition == GridRowDropPosition.After)
198+
{
199+
destinationIndex += 1;
200+
}
201+
}
202+
203+
foreach (GridModel item in args.Items)
204+
{
205+
item.ParentId = newParentId;
206+
}
207+
208+
destinationGridData.InsertRange(destinationIndex, args.Items);
209+
}
210+
211+
private void DetailGridDragChanged(bool newValue, int masterId)
212+
{
213+
DetailGridConfig[masterId].AllowDrag = newValue;
214+
}
215+
216+
private void DetailGridDropChanged(bool newValue, int masterId)
217+
{
218+
DetailGridConfig[masterId].AllowDrop = newValue;
219+
}
220+
221+
private void OnMasterGridInit(GridStateEventArgs<GridModel> args)
222+
{
223+
args.GridState.ExpandedItems = MasterGridData;
224+
}
225+
226+
private List<GridModel> MasterGridData { get; set; } = Enumerable.Range(1, 3).Select(x => new GridModel
227+
{
228+
Id = x,
229+
ParentId = null,
230+
Text = "Text " + (x)
231+
}).ToList();
232+
233+
private List<GridModel> DetailGridData { get; set; } = Enumerable.Range(1, 9).Select(x => new GridModel
234+
{
235+
Id = 100 + x,
236+
ParentId = x % 3 + 1,
237+
Text = "Text " + (100 + x)
238+
}).ToList();
239+
240+
public class GridModel
241+
{
242+
public int Id { get; set; }
243+
public int? ParentId { get; set; }
244+
public string Text { get; set; } = string.Empty;
245+
}
246+
247+
public class GridDragDropDescriptor
248+
{
249+
public TelerikGrid<GridModel>? GridRef { get; set; }
250+
public bool AllowDrag { get; set; } = true;
251+
public bool AllowDrop { get; set; } = true;
252+
}
253+
}
254+
````
255+
256+
## See Also
257+
258+
* [Grid Hierarchy](slug://components/grid/features/hierarchy)
259+
* [Grid Drag and Drop](slug://grid-drag-drop-overview)
260+
* [Set `@ref` to Detail Grids](slug://common-kb-dynamic-refs)
261+
* [Use `@key` in Grid Templates](slug://grid-kb-using-components-in-templates)

0 commit comments

Comments
 (0)