diff --git a/_config.yml b/_config.yml
index 54e794d511..28fab9c934 100644
--- a/_config.yml
+++ b/_config.yml
@@ -65,12 +65,15 @@ navigation:
"*components/grid/editing":
title: "Editing"
position: 10
+ "*components/grid/templates":
+ title: "Templates"
+ position: 25
"*components/grid/export":
title: "Export"
- position: 24
+ position: 30
"*components/grid/selection":
title: "Selection"
- position: 24
+ position: 35
"*components/chart/types":
title: "Types"
position: 15
diff --git a/components/grid/hierarchy.md b/components/grid/hierarchy.md
index 9c38bed0d9..6bbc39fdf3 100644
--- a/components/grid/hierarchy.md
+++ b/components/grid/hierarchy.md
@@ -5,7 +5,7 @@ description: Enable and configure hierarchy and detail records in Grid for Blazo
slug: components/grid/features/hierarchy
tags: telerik,blazor,grid,hierarchy,detail,detail template
published: True
-position: 25
+position: 40
---
# Grid Hierarchy
diff --git a/components/grid/manual-operations.md b/components/grid/manual-operations.md
index 5c82a390b4..bb4c6d6463 100644
--- a/components/grid/manual-operations.md
+++ b/components/grid/manual-operations.md
@@ -5,7 +5,7 @@ description: How to implement your own read, page, fiter, sort operations for th
slug: components/grid/manual-operations
tags: telerik,blazor,grid,read,filter,sort,page,manual,data,data source
published: True
-position: 50
+position: 55
---
# Manual Data Source Operations
diff --git a/components/grid/state.md b/components/grid/state.md
index 117a499089..2a5ebb2c07 100644
--- a/components/grid/state.md
+++ b/components/grid/state.md
@@ -5,7 +5,7 @@ description: Save, load, change the Grid for Blazor state - grouping, sorting, f
slug: grid-state
tags: telerik,blazor,grid,state,save,load,layout,set,change,management
published: True
-position: 40
+position: 50
---
# Grid State
diff --git a/components/grid/templates.md b/components/grid/templates.md
deleted file mode 100644
index ccb08176ea..0000000000
--- a/components/grid/templates.md
+++ /dev/null
@@ -1,490 +0,0 @@
----
-title: Templates
-page_title: Grid for Blazor | Templates
-description: Use custom templates in Grid for Blazor
-slug: components/grid/features/templates
-tags: telerik,blazor,grid,templates
-published: True
-position: 35
----
-
-# Grid Templates
-
-The Grid component can use templates for:
-* [columns (cells)](#column-template)
-* [rows](#row-template)
-* [editing of a field](#edit-template)
-* [column header](#header-template)
-* [column group footer](#column-group-footer)
-* [group header](#group-header)
-
-
-Like other Blazor content, they can receive a `context` argument that is the type of the model. To use templates, you must bind the grid to a named model.
-
-You must make sure to provide valid HTML in the templates.
-
-## Column Template
-
-By default, the grid renders the value of the field in the column, as it is provided from the data source. You can change this behavior by using the `Template` of the column and add your own content and/or logic to make a string out of the object.
-
-The example below shows how to:
-
-* set the `Template` (make sure to use the capital `T`, at the time of writing the Visual Studio autocomplete tends to use the lowercase `t` which breaks the template logic and does not allow you to access the context)
-* access the `context` of the model item so you can employ your own logic
-* set HTML in the column
-* use inline or multi-line template
-* take the field name from the model
-
->caption Using cell (column) template
-
-````CSHTML
-Cell template that renders an image based on model data
-
-
-
-
-
- @{
- var employee = context as SampleData;
-
- }
-
-
-
-
- Employee name is:
-
- @((context as SampleData).Name)
-
-
-
-
-
-
- @((context as SampleData).HireDate.ToString("dd MMM yyyy"))
-
-
-
-
-
-@code {
- public class SampleData
- {
- public int ID { get; set; }
- public string Name { get; set; }
- public DateTime HireDate { get; set; }
- }
-
- public IEnumerable MyData = Enumerable.Range(1, 50).Select(x => new SampleData
- {
- ID = x,
- Name = "name " + x,
- HireDate = DateTime.Now.AddDays(-x)
- });
-}
-````
-
->caption The result from the code snippet above
-
-
-
-## Row Template
-
-The row template allows you to define in your own code the entire contents of the `
` element the grid will render for each record. To set it, provide contents to the `` inner tag of the grid.
-
-It can be convenient if you want to use templates for most or all of the columns, as it requires less markup than setting individual templates for many columns.
-
-The contents of the row template must be `
` elements and their number (or total `colspan`) must match the number of columns defined in the grid.
-
-You can use the `Context` attribute of the `` tag of the grid to set the name of the context variable. Its type is the model type to which the grid is bound.
-
->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 and reordering cannot change the data cells anymore, only the headers, and row selection must be implemented by the app ([example](https://feedback.telerik.com/blazor/1463819)).
-
->caption Using a row template
-
-````CSHTML
-Render the entire row with your own code and logic
-
-
-
-
-
- @employee.Name
-
-
- Hired on: @(String.Format("{0:dd MMM yyyy}", employee.HireDate))
-
-
-
-
-
-
-
-
-@code {
- public class SampleData
- {
- public int ID { get; set; }
- public string Name { get; set; }
- public DateTime HireDate { get; set; }
- }
-
- public IEnumerable MyData = Enumerable.Range(1, 50).Select(x => new SampleData
- {
- ID = x,
- Name = "name " + x,
- HireDate = DateTime.Now.AddDays(-x)
- });
-}
-````
-
->caption The result from the code snippet above
-
-
-
-## Edit Template
-
-The column's `EditTemplate` defines the inline template or component that will be rendered when the user is [editing]({%slug components/grid/overview%}#editing) the field.
-
-You can data bind components in it to the current context, which is an instance of the model the grid is bound to. You will need a global variable that is also an instance of the model to store those changes. The model the template receives is a copy of the original model, so that changes can be cancelled (the `Cancel` command).
-
-If you need to perform logic more complex than simple data binding, use the change event of the custom editor component to perform it. You can also consider using a [custom edit form](https://demos.telerik.com/blazor-ui/grid/editing-custom-form).
-
->caption Sample edit template
-
-````CSHTML
-@* This example shows how to use a dropdownlist to edit strings. You can implement any desired logic instead.
-If you have an enum, the grid can edit and filter it out-of-the-box without the need for an edit template *@
-
-
-
-
-
-
-
- @{
- CurrentlyEditedEmployee = context as SampleData;
-
- }
-
-
-
- Update
- Edit
-
-
-
-
-@code {
- public SampleData CurrentlyEditedEmployee { get; set; }
-
- public void UpdateHandler(GridCommandEventArgs args)
- {
- SampleData item = (SampleData)args.Item;
-
- //perform actual data source operations here
- //if you have a context added through an @inject statement, you could call its SaveChanges() method
- //myContext.SaveChanges();
-
- var index = MyData.FindIndex(i => i.ID == item.ID);
- if (index != -1)
- {
- MyData[index] = item;
- }
- }
-
- protected override void OnInitialized()
- {
- MyData = new List();
-
- for (int i = 0; i < 50; i++)
- {
- MyData.Add(new SampleData()
- {
- ID = i,
- Name = "name " + i,
- Role = Roles[i % Roles.Count]
- });
- }
- }
-
- //in a real case, keep the models in dedicated locations, this is just an easy to copy and see example
- public class SampleData
- {
- public int ID { get; set; }
- public string Name { get; set; }
- public string Role { get; set; }
- }
-
- public List MyData { get; set; }
-
- public static List Roles = new List { "Manager", "Employee", "Contractor" };
-}
-````
-
->caption The result from the code snippet above, after Edit was clicked on the first row and the user expanded the dropdown from the template
-
-
-
-
-## Header Template
-
-Bound columns render the name of the field or their `Title` in their header. Through the `HeaderTemplate`, you can define custom content there instead of the title text.
-
->caption Sample Header Template
-
-````CSHTML
-@* Header templates override the built-in title but leave sorting indicators and filter menu icons *@
-
-
-
-
-
-
Id
- @* this is a block element and it will push the sorting indicator, see the notes below *@
-
-
-
-
- Employee Name
-
-
-
-
- Hire date
- Do something
-
- @{
- if (!string.IsNullOrEmpty(result))
- {
- @result
- }
- else
- {
-
something will appear here if you click the button
- }
- }
-
-
-
-
-
-
- Column with Icon
-
-
-
-
-
-
-@code {
- string result { get; set; }
- void DoSomething()
- {
- result = $"button in header template clicked on {DateTime.Now}, something happened";
- }
-
- public class SampleData
- {
- public int ID { get; set; }
- public string Name { get; set; }
- public DateTime HireDate { get; set; }
- }
-
- public IEnumerable MyData = Enumerable.Range(1, 50).Select(x => new SampleData
- {
- ID = x,
- Name = "name " + x,
- HireDate = DateTime.Now.AddDays(-x)
- });
-}
-````
-
->caption The result from the code snippet above
-
-
-
->note Header Templates are not available for the `GridCheckboxColumn` and the `GridCommandColumn`.
-
->note If you need to use block elements in the header templates, keep in mind that they will push the sort indicator out of its expected position. If you cannot avoid block elements (such as in the `ID` column in the example above), add a CSS rule like the ones below to adjust the sort indicator.
-
->caption Sort indicator adjustments when block elements are in the header template
-
-````CSS
-.k-grid th.k-header .k-icon.k-i-sort-asc-sm,
-.k-grid th.k-header .k-icon.k-i-sort-desc-sm {
- position: absolute;
- right: 0;
- top: 8px;
-}
-
-/* OR */
-
-.k-grid-header .k-header > .k-link {
- padding-right: 1.5em;
-}
-
- .k-grid-header .k-header > .k-link > .k-icon {
- position: absolute;
- top: 50%;
- right: 0.5em;
- transform: translateY(-50%);
- margin-left: 0;
- }
-
-.k-grid-header .k-sort-order {
- position: absolute;
- right: 0.25em;
-}
-````
-
-## Column Group Footer
-
-When the grid is grouped, the columns can display a footer with information about the column data [aggregates]({%slug grid-aggregates%}) and some custom text/logic. The template is strongly typed and exposes the available aggregates values.
-
->caption Sample Column Group Footer Template
-
-````CSHTML
-@* Group by the Team column to see the results and aggregate data in the footer *@
-
-
-
-
-
-
-
-
-
-
-
- Team Members: @context.Count
-
-
-
-
- @* you can use a group footer for non-groupable columns as well *@
- Total montly salary: @context.Sum
-
- Top paid employee: @context.Max
-
-
-
-
-
-
-
-@code {
- public List GridData { get; set; }
-
- protected override void OnInitialized()
- {
- GridData = new List();
- var rand = new Random();
- for (int i = 0; i < 15; i++)
- {
- Random rnd = new Random();
- GridData.Add(new Employee()
- {
- EmployeeId = i,
- Name = "Employee " + i.ToString(),
- Team = "Team " + i % 3,
- Salary = rnd.Next(1000, 5000),
- ActiveProjects = i % 4 == 0 ? 2 : 5
- });
- }
- }
-
- public class Employee
- {
- public int EmployeeId { get; set; }
- public string Name { get; set; }
- public string Team { get; set; }
- public decimal Salary { get; set; }
- public int ActiveProjects { get; set; }
- }
-}
-````
-
->caption The result from the code snippet above after grouping by the `Team` column
-
-
-
-## Group Header
-
-When the grid is grouped, the top row above the group provides information about the current group value by default. You can use this template to add custom content there in addition to the current value. For more information and examples, see the [Aggregates]({%slug grid-aggregates%}) article.
-
->caption Sample Group Header Template
-
-````CSHTML
-@* Group by the Team and Active Projects fields to see the results *@
-
-
-
-
-
-
-
-
-
- @context.Value @* the default text you would get without the template *@
- Team size: @context.Count
-
-
-
-
-
- @{
- Currently active projects: @context.Value
-
- //sample of conditional logic in the group header
- if ( (int)context.Value > 3) // in a real case, ensure type safety and add defensive checks
- {
- These people work on too many projects
- }
- }
-
-
-
-
-
-@code {
- public List GridData { get; set; }
-
- protected override void OnInitialized()
- {
- GridData = new List();
- var rand = new Random();
- for (int i = 0; i < 15; i++)
- {
- Random rnd = new Random();
- GridData.Add(new Employee()
- {
- EmployeeId = i,
- Name = "Employee " + i.ToString(),
- Team = "Team " + i % 3,
- Salary = rnd.Next(1000, 5000),
- ActiveProjects = i % 4 == 0 ? 2 : 5
- });
- }
- }
-
- public class Employee
- {
- public int EmployeeId { get; set; }
- public string Name { get; set; }
- public string Team { get; set; }
- public decimal Salary { get; set; }
- public int ActiveProjects { get; set; }
- }
-}
-````
-
->caption The result from the code snippet above after grouping by the `Team` and `Active Projects` columns
-
-
-
-## See Also
-
- * [Live Demo: Grid Templates](https://demos.telerik.com/blazor-ui/grid/templates)
- * [Live Demo: Grid Custom Editor Template](https://demos.telerik.com/blazor-ui/grid/customeditor)
-
diff --git a/components/grid/templates/column-group-footer.md b/components/grid/templates/column-group-footer.md
new file mode 100644
index 0000000000..44da3e4f36
--- /dev/null
+++ b/components/grid/templates/column-group-footer.md
@@ -0,0 +1,87 @@
+---
+title: Column Group Footer
+page_title: Grid for Blazor | Column Group Footer Template
+description: Use custom column group footer templates in Grid for Blazor
+slug: grid-templates-column-group-footer
+tags: telerik,blazor,grid,templates,column,group,footer
+published: True
+position: 25
+---
+
+# Column Group Footer
+
+When the grid is grouped, the columns can display a footer with information about the column data [aggregates]({%slug grid-aggregates%}) and some custom text/logic. The template is strongly typed and exposes the available aggregates values.
+
+>caption Sample Column Group Footer Template
+
+````CSHTML
+@* Group by the Team column to see the results and aggregate data in the footer *@
+
+
+
+
+
+
+
+
+
+
+
+ Team Members: @context.Count
+
+
+
+
+ @* you can use a group footer for non-groupable columns as well *@
+ Total montly salary: @context.Sum
+
+ Top paid employee: @context.Max
+
+
+
+
+
+
+
+@code {
+ public List GridData { get; set; }
+
+ protected override void OnInitialized()
+ {
+ GridData = new List();
+ var rand = new Random();
+ for (int i = 0; i < 15; i++)
+ {
+ Random rnd = new Random();
+ GridData.Add(new Employee()
+ {
+ EmployeeId = i,
+ Name = "Employee " + i.ToString(),
+ Team = "Team " + i % 3,
+ Salary = rnd.Next(1000, 5000),
+ ActiveProjects = i % 4 == 0 ? 2 : 5
+ });
+ }
+ }
+
+ public class Employee
+ {
+ public int EmployeeId { get; set; }
+ public string Name { get; set; }
+ public string Team { get; set; }
+ public decimal Salary { get; set; }
+ public int ActiveProjects { get; set; }
+ }
+}
+````
+
+>caption The result from the code snippet above after grouping by the `Team` column
+
+
+
+
+## See Also
+
+ * [Live Demo: Grid Templates](https://demos.telerik.com/blazor-ui/grid/templates)
+ * [Live Demo: Grid Custom Editor Template](https://demos.telerik.com/blazor-ui/grid/customeditor)
+
diff --git a/components/grid/templates/column-header.md b/components/grid/templates/column-header.md
new file mode 100644
index 0000000000..8d65e13ad6
--- /dev/null
+++ b/components/grid/templates/column-header.md
@@ -0,0 +1,126 @@
+---
+title: Column Header
+page_title: Grid for Blazor | Column Header Template
+description: Use custom column header templates in Grid for Blazor
+slug: grid-templates-column-header
+tags: telerik,blazor,grid,templates,column,header
+published: True
+position: 20
+---
+
+# Column Header Template
+
+Bound columns render the name of the field or their `Title` in their header. Through the `HeaderTemplate`, you can define custom content there instead of the title text.
+
+>caption Sample Header Template
+
+````CSHTML
+@* Header templates override the built-in title but leave sorting indicators and filter menu icons *@
+
+
+
+
+
+
Id
+ @* this is a block element and it will push the sorting indicator, see the notes below *@
+
+
+
+
+ Employee Name
+
+
+
+
+ Hire date
+ Do something
+
+ @{
+ if (!string.IsNullOrEmpty(result))
+ {
+ @result
+ }
+ else
+ {
+
something will appear here if you click the button
+ }
+ }
+
+
+
+
+
+
+ Column with Icon
+
+
+
+
+
+
+@code {
+ string result { get; set; }
+ void DoSomething()
+ {
+ result = $"button in header template clicked on {DateTime.Now}, something happened";
+ }
+
+ public class SampleData
+ {
+ public int ID { get; set; }
+ public string Name { get; set; }
+ public DateTime HireDate { get; set; }
+ }
+
+ public IEnumerable MyData = Enumerable.Range(1, 50).Select(x => new SampleData
+ {
+ ID = x,
+ Name = "name " + x,
+ HireDate = DateTime.Now.AddDays(-x)
+ });
+}
+````
+
+>caption The result from the code snippet above
+
+
+
+>note Header Templates are not available for the `GridCheckboxColumn` and the `GridCommandColumn`.
+
+>note If you need to use block elements in the header templates, keep in mind that they will push the sort indicator out of its expected position. If you cannot avoid block elements (such as in the `ID` column in the example above), add a CSS rule like the ones below to adjust the sort indicator.
+
+>caption Sort indicator adjustments when block elements are in the header template
+
+````CSS
+.k-grid th.k-header .k-icon.k-i-sort-asc-sm,
+.k-grid th.k-header .k-icon.k-i-sort-desc-sm {
+ position: absolute;
+ right: 0;
+ top: 8px;
+}
+
+/* OR */
+
+.k-grid-header .k-header > .k-link {
+ padding-right: 1.5em;
+}
+
+ .k-grid-header .k-header > .k-link > .k-icon {
+ position: absolute;
+ top: 50%;
+ right: 0.5em;
+ transform: translateY(-50%);
+ margin-left: 0;
+ }
+
+.k-grid-header .k-sort-order {
+ position: absolute;
+ right: 0.25em;
+}
+````
+
+## See Also
+
+ * [Live Demo: Grid Templates](https://demos.telerik.com/blazor-ui/grid/templates)
+ * [Live Demo: Grid Custom Editor Template](https://demos.telerik.com/blazor-ui/grid/customeditor)
+
diff --git a/components/grid/templates/column.md b/components/grid/templates/column.md
new file mode 100644
index 0000000000..6e33f5214c
--- /dev/null
+++ b/components/grid/templates/column.md
@@ -0,0 +1,80 @@
+---
+title: Column (Cell)
+page_title: Grid for Blazor | Column (Cell) Template
+description: Use custom column and cell templates in Grid for Blazor
+slug: grid-templates-column
+tags: telerik,blazor,grid,templates,column,cell
+published: True
+position: 5
+---
+
+# Column Template
+
+By default, the grid renders the value of the field in the column, as it is provided from the data source. You can change this behavior by using the `Template` of the column and add your own content and/or logic to make a string out of the object.
+
+The example below shows how to:
+
+* set the `Template` (make sure to use the capital `T`, at the time of writing the Visual Studio autocomplete tends to use the lowercase `t` which breaks the template logic and does not allow you to access the context)
+* access the `context` of the model item so you can employ your own logic
+* set HTML in the column
+* use inline or multi-line template
+* take the field name from the model
+
+>caption Using cell (column) template
+
+````CSHTML
+Cell template that renders an image based on model data
+
+
+
+
+
+ @{
+ var employee = context as SampleData;
+
+ }
+
+
+
+
+ Employee name is:
+
+ @((context as SampleData).Name)
+
+
+
+
+
+
+ @((context as SampleData).HireDate.ToString("dd MMM yyyy"))
+
+
+
+
+
+@code {
+ public class SampleData
+ {
+ public int ID { get; set; }
+ public string Name { get; set; }
+ public DateTime HireDate { get; set; }
+ }
+
+ public IEnumerable MyData = Enumerable.Range(1, 50).Select(x => new SampleData
+ {
+ ID = x,
+ Name = "name " + x,
+ HireDate = DateTime.Now.AddDays(-x)
+ });
+}
+````
+
+>caption The result from the code snippet above
+
+
+
+## See Also
+
+ * [Live Demo: Grid Templates](https://demos.telerik.com/blazor-ui/grid/templates)
+ * [Live Demo: Grid Custom Editor Template](https://demos.telerik.com/blazor-ui/grid/customeditor)
+
diff --git a/components/grid/templates/editor.md b/components/grid/templates/editor.md
new file mode 100644
index 0000000000..7b7b0b4a50
--- /dev/null
+++ b/components/grid/templates/editor.md
@@ -0,0 +1,99 @@
+---
+title: Editor
+page_title: Grid for Blazor | Editor Template
+description: Use custom editor templates in Grid for Blazor
+slug: grid-templates-editor
+tags: telerik,blazor,grid,templates,editor
+published: True
+position: 15
+---
+
+# Edit Template
+
+The column's `EditTemplate` defines the inline template or component that will be rendered when the user is [editing]({%slug components/grid/overview%}#editing) the field.
+
+You can data bind components in it to the current context, which is an instance of the model the grid is bound to. You will need a global variable that is also an instance of the model to store those changes. The model the template receives is a copy of the original model, so that changes can be cancelled (the `Cancel` command).
+
+If you need to perform logic more complex than simple data binding, use the change event of the custom editor component to perform it. You can also consider using a [custom edit form](https://demos.telerik.com/blazor-ui/grid/editing-custom-form).
+
+>caption Sample edit template
+
+````CSHTML
+@* This example shows how to use a dropdownlist to edit strings. You can implement any desired logic instead.
+If you have an enum, the grid can edit and filter it out-of-the-box without the need for an edit template *@
+
+
+
+
+
+
+
+ @{
+ CurrentlyEditedEmployee = context as SampleData;
+
+ }
+
+
+
+ Update
+ Edit
+
+
+
+
+@code {
+ public SampleData CurrentlyEditedEmployee { get; set; }
+
+ public void UpdateHandler(GridCommandEventArgs args)
+ {
+ SampleData item = (SampleData)args.Item;
+
+ //perform actual data source operations here
+ //if you have a context added through an @inject statement, you could call its SaveChanges() method
+ //myContext.SaveChanges();
+
+ var index = MyData.FindIndex(i => i.ID == item.ID);
+ if (index != -1)
+ {
+ MyData[index] = item;
+ }
+ }
+
+ protected override void OnInitialized()
+ {
+ MyData = new List();
+
+ for (int i = 0; i < 50; i++)
+ {
+ MyData.Add(new SampleData()
+ {
+ ID = i,
+ Name = "name " + i,
+ Role = Roles[i % Roles.Count]
+ });
+ }
+ }
+
+ //in a real case, keep the models in dedicated locations, this is just an easy to copy and see example
+ public class SampleData
+ {
+ public int ID { get; set; }
+ public string Name { get; set; }
+ public string Role { get; set; }
+ }
+
+ public List MyData { get; set; }
+
+ public static List Roles = new List { "Manager", "Employee", "Contractor" };
+}
+````
+
+>caption The result from the code snippet above, after Edit was clicked on the first row and the user expanded the dropdown from the template
+
+
+
+## See Also
+
+ * [Live Demo: Grid Templates](https://demos.telerik.com/blazor-ui/grid/templates)
+ * [Live Demo: Grid Custom Editor Template](https://demos.telerik.com/blazor-ui/grid/customeditor)
+
diff --git a/components/grid/templates/filter.md b/components/grid/templates/filter.md
new file mode 100644
index 0000000000..5b564a2ca9
--- /dev/null
+++ b/components/grid/templates/filter.md
@@ -0,0 +1,303 @@
+---
+title: Filter
+page_title: Grid for Blazor | Filter Template
+description: Use custom filter templates in Grid for Blazor
+slug: grid-templates-filter
+tags: telerik,blazor,grid,templates,filter
+published: True
+position: 35
+---
+
+
+# Filter Template
+
+The Filter Template lets you customize the appearance and logic of the built-in filters. It lets you step on the built-in filtering logic of the grid and implement your own design and logic for setting their values.
+
+There are two different templates you can use depending on the [Filter Mode]({%slug components/grid/filtering%}) that you chose:
+
+* [Filter Row Template](#filter-row-template)
+* [Filter Menu Template](#filter-menu-template)
+
+
+## Filter Row Template
+
+By default, the filter row puts an appropriate editor (like a numeric textbox for numbers) and its `ValueChanged` handler triggers grid filtering on every keystroke. There is also a button for the user to choose a filter operator, and a clear filter button when there is a value in the editor.
+
+To customize the filter cell, use the `` tag of the ``. It receives a `context` of type `FilterCellTemplateContext` that provides the following members:
+
+* `FilterDescriptor` - the object that describes the column filter. By default it has a first filter with the type and name of the field, and you can add more to its `FilterDescriptors` collection, or change its `LogicalOperator` from the default `AND`.
+
+* `FilterAsync()` - an `async` method that invokes the built-in grid filtering logic (including a handler to [`OnRead`]({%slug components/grid/manual-operations%}) if you use one) so you can call upon it easily from your template (e.g., when a value changes or a button is clicked).
+
+* `ClearFilterAsync()` - an `async` method that invokes the built-in grid clear filtering logic (including a handler to [`OnRead`]({%slug components/grid/manual-operations%}) if you use one) so you can call upon it easily from your template (e.g., when a value is cleared or a button is clicked).
+
+You can store a reference to each column's context in a field in the view-model, so you can write the handlers in the standard C# code, instead of using lambdas in the markup. You can also pass the context as a Parameter to your own separate filter component to reduce clutter in the main grid markup and code.
+
+### Examples
+
+The example below shows a custom filter that:
+
+* Implements a min-max filter in the filter cell through two numeric textboxes.
+* Filters in the `OnChange` event (only when the user presses Enter or blurs the input) to reduce database calls.
+* Shows how you can store a reference to the context or use it inline in the template.
+* Showcases building a filter descriptor with two filters and sample logic that always filters the data even if one of the inputs is empty.
+
+You can find more examples in the [Live Demo: Custom Filter Row](https://demos.telerik.com/blazor-ui/grid/custom-filter-row) that is available in your local installation under the `demos` folder.
+
+
+>caption Custom Filter Row Template - Min and Max filters on OnChange
+
+````CSHTML
+@using Telerik.DataSource
+
+The custom filter textboxes invoke filtering on Enter or blur through the OnChange event
+
+
+
+
+
+
+
+ @{
+ // we store a reference to the filter context to use in the business logic
+ // you can also use it inline in the template, like with the Clear button below
+ theFilterContext = context;
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+@code {
+ FilterCellTemplateContext theFilterContext { get; set; }
+ public decimal? MinValue { get; set; }
+ public decimal? MaxValue { get; set; }
+
+ async Task SetupFilterRule()
+ {
+ // set up min value filter - there is one default filter descriptor
+ // that alredy has the field set up, so we use that for the MIN filter
+ // and set up a value and operator
+ var filter1 = theFilterContext.FilterDescriptor.FilterDescriptors[0] as FilterDescriptor;
+ filter1.Value = MinValue == null ? int.MinValue : MinValue;
+ filter1.Operator = FilterOperator.IsGreaterThan;
+
+ // set up max value filter - we may have to crete a new filter descriptor
+ // if there wasn't one already so we prepare it first and check whether we have the second filter
+ var filter2Val = MaxValue == null ? int.MaxValue : MaxValue;
+ var filter2 = new FilterDescriptor("Price", FilterOperator.IsLessThan, filter2Val);
+ filter2.MemberType = typeof(decimal);
+
+ if (theFilterContext.FilterDescriptor.FilterDescriptors.Count > 1)
+ {
+ theFilterContext.FilterDescriptor.FilterDescriptors[1] = filter2;
+ }
+ else
+ {
+ theFilterContext.FilterDescriptor.FilterDescriptors.Add(filter2);
+ }
+
+ // ensure logical operator between the two filters is AND (it is the default, but we showcase the option)
+ theFilterContext.FilterDescriptor.LogicalOperator = FilterCompositionLogicalOperator.And;
+
+ // invoke filtering through the method the context provides
+ await theFilterContext.FilterAsync();
+ }
+
+
+ // sample grid data
+
+ public List GridData { get; set; } = Enumerable.Range(1, 50).Select(x => new SampleData
+ {
+ Id = x,
+ Price = x * 0.5m,
+ ProductName = $"Product {x}"
+ }).ToList();
+
+ public class SampleData
+ {
+ public int Id { get; set; }
+ public decimal Price { get; set; }
+ public string ProductName { get; set; }
+ }
+}
+
+@* sample CSS rule to align the custom label elements in the filter cell *@
+
+````
+
+>caption The result from the code snippet above after filtering
+
+
+
+
+## Filter Menu Template
+
+By default, the filter menu contains two filter values that are tied with a logical operator - OR or AND, with filgering being triggered through a dedicated Filter button and a Clear button removes the filter.
+
+To customize the filter menu, use the `` tag of the ``. The `Filter` and `Clear` buttons are still available below the template.
+
+The template receives a `context` of type `FilterMenuTemplateContext` that provides the following members:
+
+* `FilterDescriptor` - the object that describes the column filter. By default it has two filters with the type and name of the field, and you can add more to its `FilterDescriptors` collection, or change its `LogicalOperator` from the default `AND`.
+
+You can store a reference to each column's context in a field in the view-model, so you can reference it from event handlers in the standard C# code, instead of passing it as a nargument to lambdas in the markup only. You can also pass the context as a Parameter to your own separate filter component to reduce clutter in the main grid markup and code.
+
+### Examples
+
+The example below shows a custom filter that:
+
+* Implements a multi checkbox filter that lets the user choose several values from the data source.
+* Shows how you can store a reference to the context or use it inline in the template.
+* Showcases building multiple filter descriptors for each value the user chooses.
+
+You can find more examples in the [Live Demo: Custom Filter Menu](https://demos.telerik.com/blazor-ui/grid/custom-filter-menu) that is available in your local installation under the `demos` folder.
+
+
+>caption Custom Filter Menu Template - Multiple Checkboxes
+
+````CSHTML
+@using Telerik.DataSource
+
+This custom filter menu lets you choose more than one option to match against the data source
+
+
+
+
+
+
+
+ @{
+ // we store a reference to the filter context to use in the business logic to show we can
+ // we could, alternatively pass it as an argument to the event handler in the lambda expression
+ // which can be useful if you want to use the same filter for several columns
+ // you could then pass more arguments to the business logic such as field name and so on
+ theFilterContext = context;
+ }
+
+ @foreach (var size in Sizes)
+ {
+
+
+
+
+
+ }
+
+
+
+
+
+
+
+@code {
+ FilterMenuTemplateContext theFilterContext { get; set; }
+ public List CheckedSizes { get; set; } = new List();
+
+ public void UpdateCheckedSizes(bool value, string itemValue)
+ {
+ // update the list of items we want to filter by
+ var isSizeChecked = CheckedSizes.Contains(itemValue);
+ if (value && !isSizeChecked)
+ {
+ CheckedSizes.Add(itemValue);
+ }
+
+ if (!value && isSizeChecked)
+ {
+ CheckedSizes.Remove(itemValue);
+ }
+
+ // prepare filter descriptor
+ var filterDescriptor = theFilterContext.FilterDescriptor;
+
+ filterDescriptor.FilterDescriptors.Clear();
+ // use the OR logical operator so we include all possible values
+ filterDescriptor.LogicalOperator = FilterCompositionLogicalOperator.Or;
+ CheckedSizes.ForEach(s =>
+ // instantiate a filter descriptor for the desired field, and with the desired operator and value
+ filterDescriptor.FilterDescriptors.Add(new FilterDescriptor("Size", FilterOperator.IsEqualTo, s))
+ );
+
+ //ensure there is at least one blank filter to avoid null reference exceptions
+ if (!filterDescriptor.FilterDescriptors.Any())
+ {
+ filterDescriptor.FilterDescriptors.Add(new FilterDescriptor());
+ }
+ }
+
+ // sample grid data
+
+ public List GridData { get; set; }
+
+ protected override void OnInitialized()
+ {
+ GridData = Enumerable.Range(1, 70).Select(x => new SampleData
+ {
+ Id = x,
+ Size = Sizes[x % Sizes.Length],
+ ProductName = $"Product {x}"
+ }).ToList();
+ base.OnInitialized();
+ }
+
+ public class SampleData
+ {
+ public int Id { get; set; }
+ public string Size { get; set; }
+ public string ProductName { get; set; }
+ }
+
+ public string[] Sizes = new string[] { "XS", "S", "M", "L", "XL" };
+}
+````
+
+>caption The result from the code snippet above, after filtering
+
+
+
+
+## See Also
+
+ * [Live Demo: Grid Custom Filter Row](https://demos.telerik.com/blazor-ui/grid/custom-filter-row)
+ * [Live Demo: Grid Custom Filter Menu](https://demos.telerik.com/blazor-ui/grid/custom-filter-menu)
+
diff --git a/components/grid/templates/group-header.md b/components/grid/templates/group-header.md
new file mode 100644
index 0000000000..af663c654e
--- /dev/null
+++ b/components/grid/templates/group-header.md
@@ -0,0 +1,90 @@
+---
+title: Group Header
+page_title: Grid for Blazor | Group Header Template
+description: Use custom group header templates in Grid for Blazor
+slug: grid-templates-group-header
+tags: telerik,blazor,grid,templates,group,header
+published: True
+position: 30
+---
+
+
+# Group Header
+
+When the grid is grouped, the top row above the group provides information about the current group value by default. You can use this template to add custom content there in addition to the current value. For more information and examples, see the [Aggregates]({%slug grid-aggregates%}) article.
+
+>caption Sample Group Header Template
+
+````CSHTML
+@* Group by the Team and Active Projects fields to see the results *@
+
+
+
+
+
+
+
+
+
+ @context.Value @* the default text you would get without the template *@
+ Team size: @context.Count
+
+
+
+
+
+ @{
+ Currently active projects: @context.Value
+
+ //sample of conditional logic in the group header
+ if ( (int)context.Value > 3) // in a real case, ensure type safety and add defensive checks
+ {
+ These people work on too many projects
+ }
+ }
+
+
+
+
+
+@code {
+ public List GridData { get; set; }
+
+ protected override void OnInitialized()
+ {
+ GridData = new List();
+ var rand = new Random();
+ for (int i = 0; i < 15; i++)
+ {
+ Random rnd = new Random();
+ GridData.Add(new Employee()
+ {
+ EmployeeId = i,
+ Name = "Employee " + i.ToString(),
+ Team = "Team " + i % 3,
+ Salary = rnd.Next(1000, 5000),
+ ActiveProjects = i % 4 == 0 ? 2 : 5
+ });
+ }
+ }
+
+ public class Employee
+ {
+ public int EmployeeId { get; set; }
+ public string Name { get; set; }
+ public string Team { get; set; }
+ public decimal Salary { get; set; }
+ public int ActiveProjects { get; set; }
+ }
+}
+````
+
+>caption The result from the code snippet above after grouping by the `Team` and `Active Projects` columns
+
+
+
+## See Also
+
+ * [Live Demo: Grid Templates](https://demos.telerik.com/blazor-ui/grid/templates)
+ * [Live Demo: Grid Custom Editor Template](https://demos.telerik.com/blazor-ui/grid/customeditor)
+
diff --git a/components/grid/images/cell-template.png b/components/grid/templates/images/cell-template.png
similarity index 100%
rename from components/grid/images/cell-template.png
rename to components/grid/templates/images/cell-template.png
diff --git a/components/grid/images/column-group-footer-template.png b/components/grid/templates/images/column-group-footer-template.png
similarity index 100%
rename from components/grid/images/column-group-footer-template.png
rename to components/grid/templates/images/column-group-footer-template.png
diff --git a/components/grid/templates/images/custom-filter-cell-min-max.png b/components/grid/templates/images/custom-filter-cell-min-max.png
new file mode 100644
index 0000000000..f5136d29e1
Binary files /dev/null and b/components/grid/templates/images/custom-filter-cell-min-max.png differ
diff --git a/components/grid/templates/images/custom-filter-menu-checkboxes.png b/components/grid/templates/images/custom-filter-menu-checkboxes.png
new file mode 100644
index 0000000000..a7f208b5b5
Binary files /dev/null and b/components/grid/templates/images/custom-filter-menu-checkboxes.png differ
diff --git a/components/grid/images/edit-template.png b/components/grid/templates/images/edit-template.png
similarity index 100%
rename from components/grid/images/edit-template.png
rename to components/grid/templates/images/edit-template.png
diff --git a/components/grid/images/group-header-template.png b/components/grid/templates/images/group-header-template.png
similarity index 100%
rename from components/grid/images/group-header-template.png
rename to components/grid/templates/images/group-header-template.png
diff --git a/components/grid/images/header-template.png b/components/grid/templates/images/header-template.png
similarity index 100%
rename from components/grid/images/header-template.png
rename to components/grid/templates/images/header-template.png
diff --git a/components/grid/images/row-template.png b/components/grid/templates/images/row-template.png
similarity index 100%
rename from components/grid/images/row-template.png
rename to components/grid/templates/images/row-template.png
diff --git a/components/grid/templates/overview.md b/components/grid/templates/overview.md
new file mode 100644
index 0000000000..5a88d27a82
--- /dev/null
+++ b/components/grid/templates/overview.md
@@ -0,0 +1,42 @@
+---
+title: Overview
+page_title: Grid for Blazor | Templates Overview
+description: Use custom templates in Grid for Blazor
+slug: components/grid/features/templates
+tags: telerik,blazor,grid,templates
+published: True
+previous_url: /grid/templates
+position: 0
+---
+
+# Grid Templates
+
+You can customize the grid appearance and behavior through the various templates it provides so you can add more details for your users such as aggregate data, format numbers and dates, use custom editing logic, implement custom filters and more.
+
+The Grid component can use templates for:
+
+* [columns (cells)]({%slug grid-templates-column%}) - the rendering of each cell (column). You can, for example, change string formats or add your own components.
+
+* [rows]({%slug grid-templates-row%}) - the entire rendering of the `tr` element of the row, so you can fully customize the grid behavior and rendering.
+
+* [editing of a field]({%slug grid-templates-editor%}) - when a cell is in edit mode, it will render this template where you can use custom editors, components and logic.
+
+* [column header]({%slug grid-templates-column-header%}) - the title portion of the column.
+
+* [column group footer]({%slug grid-templates-column-group-footer%}) - the footer of the column when the grid is [grouped]({%slug components/grid/features/grouping%}). You can use it, for example, to display [aggregates]({%slug grid-aggregates%}).
+
+* [group header]({%slug grid-templates-group-header%}) - the shared section that denotes each grid [group]({%slug components/grid/features/grouping%}).
+
+* [filter]({%slug grid-templates-filter%}) - the content of the filter cell or filter menu where you can implement custom rendering and logic for the filters.
+
+
+
+Like other Blazor content, most of them can receive a `context` argument that is the type of the model. To use templates, you must bind the grid to a named model. The filter templates are the exception as they are not related to rows and models.
+
+You must make sure to provide valid HTML in the templates.
+
+## See Also
+
+ * [Live Demo: Grid Templates](https://demos.telerik.com/blazor-ui/grid/templates)
+ * [Live Demo: Grid Custom Editor Template](https://demos.telerik.com/blazor-ui/grid/customeditor)
+
diff --git a/components/grid/templates/row.md b/components/grid/templates/row.md
new file mode 100644
index 0000000000..fb9b97d9b9
--- /dev/null
+++ b/components/grid/templates/row.md
@@ -0,0 +1,70 @@
+---
+title: Row
+page_title: Grid for Blazor | Row Template
+description: Use custom row templates in Grid for Blazor
+slug: grid-templates-row
+tags: telerik,blazor,grid,templates,row
+published: True
+position: 10
+---
+
+# Row Template
+
+The row template allows you to define in your own code the entire contents of the `
` element the grid will render for each record. To set it, provide contents to the `` inner tag of the grid.
+
+It can be convenient if you want to use templates for most or all of the columns, as it requires less markup than setting individual templates for many columns.
+
+The contents of the row template must be `
` elements and their number (or total `colspan`) must match the number of columns defined in the grid.
+
+You can use the `Context` attribute of the `` tag of the grid to set the name of the context variable. Its type is the model type to which the grid is bound.
+
+>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 and reordering cannot change the data cells anymore, only the headers, and row selection must be implemented by the app ([example](https://feedback.telerik.com/blazor/1463819)).
+
+>caption Using a row template
+
+````CSHTML
+Render the entire row with your own code and logic
+
+
+
+
+
+ @employee.Name
+
+
+ Hired on: @(String.Format("{0:dd MMM yyyy}", employee.HireDate))
+
+
+
+
+
+
+
+
+@code {
+ public class SampleData
+ {
+ public int ID { get; set; }
+ public string Name { get; set; }
+ public DateTime HireDate { get; set; }
+ }
+
+ public IEnumerable MyData = Enumerable.Range(1, 50).Select(x => new SampleData
+ {
+ ID = x,
+ Name = "name " + x,
+ HireDate = DateTime.Now.AddDays(-x)
+ });
+}
+````
+
+>caption The result from the code snippet above
+
+
+
+
+## See Also
+
+ * [Live Demo: Grid Templates](https://demos.telerik.com/blazor-ui/grid/templates)
+ * [Live Demo: Grid Custom Editor Template](https://demos.telerik.com/blazor-ui/grid/customeditor)
+
diff --git a/components/grid/toolbar.md b/components/grid/toolbar.md
index 4c15174e30..2fda9a1ddf 100644
--- a/components/grid/toolbar.md
+++ b/components/grid/toolbar.md
@@ -5,7 +5,7 @@ description: Use toolbar and custom actions in Grid for Blazor
slug: components/grid/features/toolbar
tags: telerik,blazor,grid,toolbar
published: True
-position: 30
+position: 45
---
# Grid Toolbar
diff --git a/components/grid/virtual-scrolling.md b/components/grid/virtual-scrolling.md
index 056ee4cbf8..8af095abf3 100644
--- a/components/grid/virtual-scrolling.md
+++ b/components/grid/virtual-scrolling.md
@@ -5,7 +5,7 @@ description: Enable and configure virtual scrolling in Grid for Blazor
slug: components/grid/virtual-scrolling
tags: telerik,blazor,grid,virtual,scrolling
published: True
-position: 55
+position: 60
---
# Virtual Scrolling