Skip to content

Commit 527b7f5

Browse files
committed
docs(Grid): Add KB for implement built-in functions when using RowTemplate
1 parent 4578741 commit 527b7f5

File tree

3 files changed

+303
-2
lines changed

3 files changed

+303
-2
lines changed

components/grid/selection/rows.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ The [**Select All** checkbox in the Grid checkbox column]({%slug components/grid
199199
When using [Grid templates]({%slug components/grid/features/templates%}) with row selection:
200200

201201
* If you are using a [Grid column template]({%slug grid-templates-column%}) and you have a clickable element in the template, you can check the knowledge base article on [how to prevent row selection when the user clicks another component in the Grid column template]({%slug grid-kb-row-selection-in-column-template%}).
202-
* If you are using a [row template]({%slug components/grid/features/templates%}#row-template) the Grid cannot render a built-in [checkbox column]({%slug components/grid/columns/checkbox%}). You have to render checkboxes manually and handle their changed event to populate the `SelectedItems` collection of the Grid. You can find an example to get started in the following thread: [Grid Row Template with Selection - Unsure how to Bind to Selected Item](https://feedback.telerik.com/blazor/1463819-grid-row-template-with-selection-unsure-how-to-bind-to-selected-item).
202+
* If you are using a [row template]({%slug components/grid/features/templates%}#row-template) the Grid cannot render a built-in [checkbox column]({%slug components/grid/columns/checkbox%}). You have to render checkboxes manually and handle their changed event to populate the `SelectedItems` collection of the Grid. You can find an example to get started in the following knowledge base article: [Implement Built-in Functions when Using Grid Row Template]({%slug grid-kb-row-template-simulate-built-in-functions%}).
203203

204204
### Selection and Row Drag and Drop
205205

components/grid/templates/row.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ The contents of the row template must be `<td>` elements and their number (or to
1818

1919
You can use the `Context` attribute of the `<RowTemplate>` tag of the grid to set the name of the context variable. Its type is the model type to which the grid is bound.
2020

21-
>important Using the row template takes functionality away from the grid because it no longer controls its own rendering. For example, InCell and Inline editing could not render editors, detail templates will not be available, column resizing, locking, visibility and reordering cannot change the data cells anymore, only the headers, and Checkbox selection must be implemented by the app ([example](https://feedback.telerik.com/blazor/1463819)).
21+
>important Using the row template takes functionality away from the grid because it no longer controls its own rendering. For example, InCell and Inline editing could not render editors, detail templates will not be available, column resizing, locking, visibility and reordering cannot change the data cells anymore, only the headers, and Checkbox selection must be implemented by the app. You can find an example to get started in the following knowledge base article: [Implement Built-in Functions when Using Grid Row Template]({%slug grid-kb-row-template-simulate-built-in-functions%}).
2222
2323
>caption Using a row template
2424
Lines changed: 301 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,301 @@
1+
---
2+
title: Add the Built-in for the Grid Functions when Using Grid Row Template
3+
description: How to implement built-in functions when using Grid RowTemplate
4+
type: how-to
5+
page_title: Implement Built-in Functions when Using Grid Row Template
6+
slug: grid-kb-row-template-simulate-built-in-functions
7+
position:
8+
tags: grid, rowtemplate
9+
ticketid: 1463819, 1465447, 1578974, 1605222, 1606211, 1609036, 1629221, 1667096
10+
res_type: kb
11+
---
12+
13+
## Environment
14+
15+
<table>
16+
<tbody>
17+
<tr>
18+
<td>Product</td>
19+
<td>Grid for Blazor</td>
20+
</tr>
21+
</tbody>
22+
</table>
23+
24+
25+
## Description
26+
27+
This KB article answers the following questions:
28+
29+
* How to [select rows]({%slug grid-selection-row%}) in Grid when using a [Row Template]({%slug grid-templates-row%})?
30+
* How to add [Checkbox column]({%slug components/grid/columns/checkbox%}) in Grid when using a Row Template? I want to be able to select the row through its checkbox, but also to have the functionallity to [select all rows]({%slug components/grid/columns/checkbox%}#parameters) from the header of the Checkbox column.
31+
* Do the built-in keyboard options to select a range of rows by clicking the **Shift** or **Ctrl** key work when using a Row Template? How to check the checkbox of the row when I select a row by clicking on the row?
32+
* How to add [command column]({%slug components/grid/columns/command%}) in Grid when using a Row Template?
33+
* When using a Row Template how to prevent selection of Grid rows when clicking on command buttons?
34+
* How to implement Grid column [resizing]({%slug components/grid/columns/resize%}), [auto-fitting]({%slug components/grid/columns/resize%}#autofit-columns), [visibility]({%slug grid-columns-visible%}), [locking]({%slug grid-columns-frozen%}), and [reordering]({%slug components/grid/columns/reorder%}) when using a Row Template?
35+
36+
## Solution
37+
38+
By default, using the Row Template takes the majority of built-in functionalities away from the Grid because the Grid no longer controls its own rendering. This gives you the controll to add your own implementation for them. The example below showcases a possible implementation of some of the functionalities, such as row selection by clicking on a row and through a Checkbox column, column resizing and visibility, editing through command buttons, sorting, filtering.
39+
40+
### Selection
41+
42+
* In the [`<GridColumns>` collection]({%slug components/grid/columns/bound%}#show-data-in-a-grid) add the [`<GridCheckboxColumn>`]({%slug components/grid/columns/checkbox%}) and use the [`HeaderTemplate`]({%slug components/grid/columns/checkbox%}#header-template) to add a custom [CheckBox component]({%slug checkbox-overview%}). This CheckBox component handles the [select all rows]({%slug components/grid/columns/checkbox%}#parameters) functionallity.
43+
* In the `<RowTemplate>` add a `<td>` element with custom CheckBox component. Add a boolean property to the Grid model to indicate selection so you can use it for the state of this CheckBox.
44+
* Handle the Grid [`SelectedItemsChanged` event]({%slug grid-selection-row%}#selecteditemschanged-event) and the CheckBox [`OnChange` event]({%slug checkbox-events%}#onchange) to manage the [`SelectedItems` collection]({%slug grid-selection-overview%}#access-selected-rows-or-cells). The `OnChange` event fires after the `SelectedItemsChanged` event. In this case you need to create a separate collection of selected items to persist the selected items when multiselecting through the CheckBox.
45+
46+
### Editing, Sorting, Filtering
47+
48+
The built-in editing, sorting, filtering will work if the RowTemplate structure is similar to an actual table and only for the first included in the `<td>` element Grid data model property, if such.
49+
50+
### Command column
51+
52+
* In the `<GridColumns>` collection add the [`<GridCommandColumn>`]({%slug components/grid/columns/command%}) and use the [built-in `Save` and `Cancel` commands]({%slug components/grid/columns/command%}#built-in-commands).
53+
* In the `<RowTemplate>` add a `<td>` element with custom [Button component]({%slug components/button/overview%}) and handle the Grid items editing and deleting programatically. You can refer to the knowledge base article on how to [enter and exit Grid edit Mode programmatically]({%slug grid-kb-add-edit-state%}).
54+
* Set the <a href="https://developer.mozilla.org/en-US/docs/Web/API/Event/stopPropagation" target="_blank">`stopPropagation` method</a> of the <a href="https://www.w3schools.com/jsref/event_onclick.asp" target="_blank">`onclick` event</a> to the `<td>` element to prevent row selection when clicking on a command button.
55+
56+
### Column Resizing, Auto-fitting, Visibility, Locking, Reordering
57+
58+
* The column resizing and auto-fitting may work as usual, if the RowTemplate structure is similar to an actual table row with coresponding number of cells to the number of Grid columns.
59+
* The column visibility depends if you include a `<td>` element for the column in the Row Template.
60+
* To implement column locking you need to add the `k-grid-content-sticky` class to the `<td>` element for the columns that you want to be locked as well as calculate and set the correct `left` and `right` CSS properties as the content inside the template can be any (valid) HTML.
61+
* When you want to have a column reordering you need to manage the `left` and `right` CSS properties to the `<td>` elements in the RowTemplate.
62+
63+
## Example
64+
65+
>caption Row selection, Column resizing and visibility, Editing, Sorting, Filtering when using Row Template
66+
67+
````CSHTML
68+
<TelerikGrid @ref="@GridRef"
69+
Data=@GridData
70+
Pageable="true"
71+
PageSize="15"
72+
Page="1"
73+
Sortable="true"
74+
Resizable="true"
75+
FilterMode="@GridFilterMode.FilterMenu"
76+
FilterMenuType="@FilterMenuType.CheckBoxList"
77+
EditMode="@GridEditMode.Inline"
78+
SelectionMode="@GridSelectionMode.Multiple"
79+
SelectedItems="@SelectedItems"
80+
SelectedItemsChanged="@( (IEnumerable<ArticleDto> newSelected) => SelectedItemsChangedHandler(newSelected) )"
81+
OnCreate="@OnCreateHandler"
82+
OnUpdate="@OnUpdateHandler">
83+
<GridToolBarTemplate>
84+
<GridCommandButton Command="Add">Add</GridCommandButton>
85+
</GridToolBarTemplate>
86+
<RowTemplate Context="article">
87+
<td>
88+
<TelerikCheckBox @bind-Value="@article.IsSelected" OnChange="@(() => OnCheckBoxChangeHandler(article.Id))" />
89+
</td>
90+
<td>
91+
<img src="@article.ImageUrl" width="55" height="35" />
92+
</td>
93+
<td>
94+
@{
95+
if(article.IsSelected)
96+
{
97+
<h2>Selected</h2>
98+
}
99+
else
100+
{
101+
<h2>Not Selected</h2>
102+
}
103+
}
104+
@article.Title
105+
</td>
106+
<td @onclick:stopPropagation="true">
107+
<TelerikButton Icon="@SvgIcon.Pencil" OnClick="@(() => OnProgrammaticEditHandler(article.Id))">Programmatic Edit</TelerikButton>
108+
<TelerikButton Icon="@SvgIcon.Trash" OnClick="@(() => OnProgrammaticDeleteHandler(article.Id))">Programmatic Delete</TelerikButton>
109+
</td>
110+
</RowTemplate>
111+
<GridColumns>
112+
<GridCheckboxColumn>
113+
<HeaderTemplate>
114+
<TelerikCheckBox Value="@SelectAll" ValueChanged="@((bool value) => SelectAllHandler(value))" />
115+
</HeaderTemplate>
116+
</GridCheckboxColumn>
117+
<GridColumn Field=@nameof(ArticleDto.Id) Visible="false" />
118+
<GridColumn Field=@nameof(ArticleDto.ImageUrl) Title="Image" Editable="false" Resizable="true" />
119+
<GridColumn Field=@nameof(ArticleDto.Title) Title="Article Title" Resizable="true" />
120+
<GridCommandColumn>
121+
<GridCommandButton Icon="SvgIcon.Save" Command="Save" ShowInEdit="true">Update</GridCommandButton>
122+
<GridCommandButton Icon="SvgIcon.Cancel" Command="Cancel" ShowInEdit="true">Cancel</GridCommandButton>
123+
</GridCommandColumn>
124+
</GridColumns>
125+
</TelerikGrid>
126+
127+
@code {
128+
private TelerikGrid<ArticleDto>? GridRef { get; set; }
129+
130+
private List<ArticleDto> GridData { get; set; } = new();
131+
132+
private IEnumerable<ArticleDto> SelectedItems { get; set; } = Enumerable.Empty<ArticleDto>();
133+
private List<ArticleDto> TempSelectedItemsCollection { get; set; } = new();
134+
private bool SelectAll { get; set; }
135+
136+
#region Selection
137+
private void SelectAllHandler(bool newValue)
138+
{
139+
SelectAll = newValue;
140+
141+
foreach (var item in GridData)
142+
{
143+
item.IsSelected = SelectAll;
144+
}
145+
146+
// If SelectAll is true, assign all items to SelectedItems,
147+
// else set it to an empty list
148+
SelectedItems = SelectAll ? new List<ArticleDto>(GridData) : new List<ArticleDto>();
149+
TempSelectedItemsCollection = SelectAll ? new List<ArticleDto>(GridData) : new List<ArticleDto>();
150+
}
151+
152+
protected void SelectedItemsChangedHandler(IEnumerable<ArticleDto> selectedItems)
153+
{
154+
foreach (var item in GridData)
155+
{
156+
item.IsSelected = false;
157+
}
158+
159+
// Use temporary collection to be able to persist the
160+
// selected items when multiselecting with checkboxes
161+
TempSelectedItemsCollection = SelectedItems.ToList();
162+
SelectedItems = selectedItems;
163+
164+
foreach (var item in selectedItems)
165+
{
166+
item.IsSelected = true;
167+
}
168+
}
169+
170+
private void OnCheckBoxChangeHandler(Guid itemId)
171+
{
172+
ArticleDto? currentItem = GridData.FirstOrDefault(a => a.Id == itemId);
173+
174+
if (currentItem != null)
175+
{
176+
if (currentItem.IsSelected)
177+
{
178+
TempSelectedItemsCollection.Add(currentItem);
179+
}
180+
else
181+
{
182+
TempSelectedItemsCollection.Remove(currentItem);
183+
}
184+
}
185+
186+
// The OnChange event fires after the SelectedItemsChanged
187+
// thus we need to update the SelectedItems collection
188+
SelectedItems = TempSelectedItemsCollection;
189+
190+
foreach (var item in SelectedItems)
191+
{
192+
item.IsSelected = true;
193+
}
194+
}
195+
#endregion Selection
196+
#region Edit
197+
198+
private void OnCreateHandler(GridCommandEventArgs args)
199+
{
200+
var createdItem = (ArticleDto)args.Item;
201+
createdItem.Id = Guid.NewGuid();
202+
var rnd = new Random();
203+
createdItem.ImageUrl = $"https://demos.telerik.com/blazor-ui/images/photos/{rnd.Next(1, 30) % 7 + 1}.jpg";
204+
GridData.Insert(0, createdItem);
205+
}
206+
207+
private async Task OnProgrammaticEditHandler(Guid itemId)
208+
{
209+
if (GridData.Any() && GridRef != null)
210+
{
211+
var gridState = GridRef.GetState();
212+
213+
gridState.InsertedItem = null;
214+
gridState.OriginalEditItem = GridData.Where(x => x.Id == itemId).First();
215+
gridState.EditItem = GridData.Where(x => x.Id == itemId).First().Clone();
216+
var rnd = new Random();
217+
gridState.EditItem.ImageUrl = $"https://demos.telerik.com/blazor-ui/images/photos/{rnd.Next(1, 30) % 7 + 1}.jpg";
218+
await GridRef.SetStateAsync(gridState);
219+
}
220+
}
221+
222+
private void OnUpdateHandler(GridCommandEventArgs args)
223+
{
224+
var updatedItem = (ArticleDto)args.Item;
225+
var index = GridData.FindIndex(i => i.Id == updatedItem.Id);
226+
if (index != -1)
227+
{
228+
GridData[index] = updatedItem;
229+
}
230+
}
231+
232+
private void OnProgrammaticDeleteHandler(Guid itemId)
233+
{
234+
if (GridData.Any() && GridRef != null)
235+
{
236+
var itemToDelete = GridData.Where(x => x.Id == itemId).First();
237+
GridData.Remove(itemToDelete);
238+
239+
// Remove from SelectedItems collection
240+
TempSelectedItemsCollection = SelectedItems.ToList();
241+
TempSelectedItemsCollection.Remove(itemToDelete);
242+
SelectedItems = TempSelectedItemsCollection;
243+
244+
GridRef.Rebind();
245+
}
246+
}
247+
#endregion Edit
248+
#region DataGeneration
249+
250+
private void GetGridData()
251+
{
252+
GridData = new List<ArticleDto>();
253+
254+
for (int i = 1; i <= 30; i++)
255+
{
256+
GridData.Add(new ArticleDto
257+
{
258+
Id = Guid.NewGuid(),
259+
Title = "Article title " + i,
260+
ImageUrl = $"https://demos.telerik.com/blazor-ui/images/photos/{i % 7 + 1}.jpg"
261+
});
262+
}
263+
}
264+
265+
protected override void OnInitialized()
266+
{
267+
GetGridData();
268+
}
269+
270+
public class ArticleDto
271+
{
272+
public Guid Id { get; set; }
273+
public string Title { get; set; }
274+
public string ImageUrl { get; set; }
275+
public bool IsSelected { get; set; }
276+
277+
public ArticleDto Clone()
278+
{
279+
return new ArticleDto()
280+
{
281+
Id = Id,
282+
Title = Title,
283+
ImageUrl = ImageUrl
284+
};
285+
}
286+
}
287+
#endregion DataGeneration
288+
}
289+
````
290+
291+
## See Also
292+
293+
* [Grid Row Template]({%slug grid-templates-row%})
294+
* [Grid Row Selection]({%slug grid-selection-row%})
295+
* [Grid Command Column]({%slug components/grid/columns/command%})
296+
* [Grid Column Resizing]({%slug components/grid/columns/resize%})
297+
* [Grid Column Auto-fitting]({%slug components/grid/columns/resize%}#autofit-columns)
298+
* [Grid Column Visibility]({%slug grid-columns-visible%})
299+
* [Grid Column Locking]({%slug grid-columns-frozen%})
300+
* [Grid Column Reordering]({%slug components/grid/columns/reorder%})
301+
* [Enter And Exit Grid Edit Mode Programmatically]({%slug grid-kb-add-edit-state%})

0 commit comments

Comments
 (0)