Hi All,
Just wondering if kendo can have multifunction toolbar.
I know that its not out of the box but wanted to know if toolbar cable of
- Adding Field drowpdown with search
- breadcrumb based on dynamic filter set by user
- client can add as many condition as he want
Note that toolbar.ClientTemplate(@<text>html template here</text> is giving me error on my Razor page
Please see screenshot taken from SeviceNow
Thanks!
Ryan
30 Answers, 1 is accepted
Hi Ryan,
The toolbar of the Kendo UI Grid could be fully customized and HTML of choice could be applied. However, it would have to be set up with the Template option, rather than the ClientTemplate. You could check out a more detailed live demo here:
https://demos.telerik.com/aspnet-mvc/grid/toolbar-template
In case further assistance is required, let me know.
Best regards,
Tsvetomir
Progress Telerik

Hi Tsvetomir, I already tried that but im having error when I add @<text>
Please see sample proj. I commented out the code at the moment
Hi Ryan,
I have investigated the provided project and I have noticed that is it created in an ASP.NET Core environment. The toolbar template for this framework is different than the one for ASP.NET MVC. I can recommend following the example that is set in the following demo:
https://demos.telerik.com/aspnet-core/grid/toolbar-template
As well as, alternating the template declaration of your project as shown below does not trigger an exception:
.ToolBar(toolbar =>
{
toolbar.ClientTemplate("<div class='refreshBtnContainer'>"+
"<a href='\\#' class='k-pager-refresh k-link k-button k-button-icon' title='Refresh'><span class='k-icon k-i-reload'></span></a>"+
"</div>"+
"<div class='toolbar'>"+
"<label class='category-label' for='category'>Show products by category:</label>"+
"</div>"
);
})
In case further clarification is needed, let me know.
Best regards,
Tsvetomir
Progress Telerik

Hi Tsvetomir,
How can I combine toolbar.Search() and toolbar.ClientTemplateId('GridTemplate')?
.ToolBar(t =>
{
t.ClientTemplateId("GridToolbarTemplate");
t.Search();
}
)
With code above it only shows the Search and not the template. if I remove t.Search(), it will show my template.
Thanks!
Ryan

Got it.
But I'm thinking is how to filter based on selected field. I have created dropdown with value Email/First Name/Last Name/Status etc. I would like to search based on selected item on the dropdown and search box text. any sample code.
Thanks!
Hello Ryan,
My name is Nikolay and I am stepping in while my colleague Tsvetomir is absent.
For the first question, I believe you already have an answer in thread 1452924.
Regarding the second one If I understand correctly you need to filter the Grid based on a selected value from a dropdown list in the toolbar. This could be achieved following the approach shown in the below Toolbar template demo:
In case the requirement is different, please share more details on it so I could help further.
Regards,
Nikolay
Progress Telerik

Hi Nikolay,
Its not just a dropdown list that will trigger the filter. There will be a text box after the dropdown list.
If I select email from dropdown list and type on the search box it will do search like for sql: select * from table where email like '%textbox value%'
If I select first name from dropdown list and type on the search box it will do search like for sql: select * from table where firstname like '%textbox value%'
and so on.
It will only search based on selected item on the dropdown list.
What will be the filter to my kendo grid?
Will be able to get value of both dropdown and textbox but how to use it to kendo grid.
Sample code would help.
Thanks again for your help!
on my other post, theres no answer yet on adding breadcrumb to kendo grid toolbar. Dont know why its not showing up.
https://www.telerik.com/forums/adding-breadcrumb-to-my-kendo-grid-toolbar-template-not-working
Thank you.
Hi Ryan,
Based on the values from the Kendo UI DropDownList and the text box, you should apply a filter to the grid programmatically. You could do so by passing the respective values to the filter() method of the data source:
https://docs.telerik.com/kendo-ui/api/javascript/data/datasource/methods/filter
If you would like to pass multiple filter expressions, you should pass an array of objects each containing the value and operator.
As per the other ticket, I would like to inform you that a support engineer has already been assigned and will get back to you within the specified time frame. For the forum tickets, the time frame is 72 hours.
Nevertheless, let me know in case additional information is needed.
Regards,
Tsvetomir
Progress Telerik

Very nice.
How about for multiple filter like adding AND/OR/Sort, and other types of filter. Is filter will be like an array object?
or like filtering in MongoDB?
sample query in MongoDB:
{$filter: {input: [ 1, "a", 2, null, 3.1, NumberLong(4), "5" ],as: "num",cond: { $and: [{ $gte: [ "$$num", NumberLong("-9223372036854775807") ] },{ $lte: [ "$$num", NumberLong("9223372036854775807") ] }] }}}
Do you have sample that I can check for muliple filtering:
I'd like to know if this kind of operator can be handled:
starts with
ends with
contains
does not contain
is
is not
is empty
is not empty
is anything
is one of
is empty string
lass that or is
greater than or is
between
is same
is different
Please note that I'm working on dynamic multiple filtering with sorting that user can create on their own and have it saved as a template. so that when they go back their filter is already set.. Please see attached.
Thank you so much Tsvetomir!
Hi Ryan,
You could pass multiple filter expressions as shown in the code snippet below:
$("#grid").getKendoGrid().dataSource.filter({
filters: [{field:"Freight", operator: "eq", value:32.38},
{field:"ShipName", operator: "contains", value:"vins"}],
logic: "and"
})
If you would like to perform multiple operations such as sorting and filtering simultaneously, make use of the query() method:
https://docs.telerik.com/kendo-ui/api/javascript/data/datasource/methods/query
Since you would like to persist the applied options of the grid, you might consider the following approach as well:
https://demos.telerik.com/aspnet-mvc/grid/persist-state
Regards,
Tsvetomir
Progress Telerik

Very Nice,
Thank you so much Tsvetomir!
Is filter limited to just 2 condition and you cannot mix AND
with OR. For instance I have 3 conditions the first 2 is AND and last is OR.
Is that Possible?
Lastly how to change .Read dynamically from client side? Just
like on filter?
.DataSource(ds => ds.Ajax()
.Read(r =>
r.Url("/Account/Users?handler=Read&route=api/getUsers").Data("forgeryToken"))
.Model(m => m.Id(id => id.UserNumber))
.PageSize(20)
)
I have added route query above and it was handled ok on
serverside. Now how can I change value of route?
I used .Read(r =>
r.Url("/Account/Admin?handler=Read&route=" +
Model.route).Data("forgeryToken"))
but can update Model from client side.
also tried + $("#route").val(); but got error right
away.
Any suggestion on how to achieve this?
Thank you again and again.
Hi Ryan,
The data source could be filtered by more than two fields simultaneously. Also, you could mix the logic operators. Here is an example of multiple filter expressions applied to the data source:
dataSource.filter({
logic: "or",
filters: [
{ field: "fieldA", operator: "eq", value: 100 },
{
logic: "and",
filters: [
{ field: "fieldA", operator: "lt", value: 100 },
{ field: "fieldB", operator: "eq", value: true }
]
}
]
});
As per changing the route parameters, I would recommend actually taking advantage of the data option. You could submit the additional parameters along with the forgery token as shown here:
function additionalData() {
return $.extend(true, {}, kendo.antiForgeryTokens(), {companyId: '@Model.route'});
}
Alternatively, you could change the read declaration by passing the new values within the setOptions method. More information could be found here:
https://docs.telerik.com/kendo-ui/api/javascript/ui/grid/methods/setoptions
I hope you find this helpful.
Regards,
Tsvetomir
Progress Telerik

Nice, so I can now have multiple filter. Thanks for the sample. Where can I find the list of all available operator? e.g. "eq" "lt"
Again follow up on dynamic datasource. Cant seem to make it work.
please note that Datasource.Read I have added "&route=api/getUsers" that I need to change it clients side.
my Serverside able to handle that route parameter with no issue
public async Task<JsonResult> OnPostRead([DataSourceRequest] DataSourceRequest request, string route)
{...}
my grid client side:
@(Html.Kendo().Grid<UsersList>()
.Name("grid")
.DataSource(ds => ds.Ajax()
.Read(r => r.Url("/Account/Admin?handler=Read&route=api/getUsers").Data("forgeryToken"))
.Create(c => c.Url("/Account/Admin?handler=Create"))
.Model(m => m.Id(id => id.UserNumber))
.PageSize(20)
))
Now I just wanted to change the Datasource.Read from
.Read(r => r.Url("/Account/Admin?handler=Read&route=api/getUsers").Data("forgeryToken"))
to
.Read(r => r.Url("/Account/Admin?handler=Read&route=api/getContacts").Data("forgeryToken"))
on client side using my dropdown list if Contact is selected
my code below does not work. just testing out any possible way to chane datasource.read on dropdown change
function onChangeDatasource(e) {
if (e.dataItem) {
var dataItem = e.dataItem;
var grid = $("#grid").data("kendoGrid");
switch (dataItem) {
case "Users":
// how to set Grid Datasource.Read?
grid.setOptions({
DataSource: (ds => ds.Ajax()
.Read(r => r.Url("/Account/Admin?handler=Read&route=api/List/GetUsers").Data("forgeryToken"))
.Create(c => c.Url("/Account/Admin?handler=Create"))
.Model(m => m.Id(id => id.UserNumber))
.PageSize(20)
)
});
break;
case "Contacts":
// how to set Grid Datasource.Read?
grid.setOptions({
DataSource: (ds => ds.Ajax()
.Read(r => r.Url("/Account/Admin?handler=Read&route=api/List/GetContacts").Data("forgeryToken"))
.Create(c => c.Url("/Account/Admin?handler=Create"))
.Model(m => m.Id(id => id.ContactNumber))
.PageSize(20)
)
});
break;
case "Employees":
// how to set Grid Datasource.Read?
grid.setOptions({
DataSource: (ds => ds.Ajax()
.Read(r => r.Url("/Account/Admin?handler=Read&route=api/List/GetEmployees").Data("forgeryToken"))
.Create(c => c.Url("/Account/Admin?handler=Create"))
.Model(m => m.Id(id => id.EmployeeNumber))
.PageSize(20)
)
});
break;
default:
// code block
}
//$('.k-pager-refresh').click();
}
};
the $("#grid").getKendoGrid().dataSource.filter({.... works here,
just wondering if there are code to change .dataSource.Read
or perhaps pass parameters to my serveside route from client side
public async Task<JsonResult> OnPostRead([DataSourceRequest] DataSourceRequest request, string route)
Please let me know how to make it work. Thank you again for your help.
Hi Ryan,
The full list of operators for each of the data types could be found at the bottom of the following article:
https://docs.telerik.com/kendo-ui/api/javascript/ui/grid/configuration/filterable.operators
As per setting the new URL for the read request of the data source, the arguments set in the setOptions method have to be in JavaScript:
$("#grid").getKendoGrid().setOptions({
dataSource:{
transport:{
read:{
url:"myNewUrl",
data: forgeryToken
}
}
}
})
I hope you find this helpful.
Regards,
Tsvetomir
Progress Telerik

Wow it worked!!! Thank you so much.
I can now pass value and work with different datasource.
Just got 1 problem though.
My controls got distorted after clicking Contacts. Please see image attached.
This is my code form dropdown select change
function onSelectDS(e) {
if (e.dataItem) {
var dataItem = e.dataItem;
var grid = $("#grid").data("kendoGrid");
grid.setOptions({
dataSource: {
transport: {
read: {
url: "/Account/Admin?handler=Read&route=api/List/" + dataItem,
data: forgeryToken
}}}})
}
}
Any Idea why my header template controls got distorted after calling the setOptions?
Hi Ryan,
I am glad to hear that you have managed to successfully replace the URL of the Read request.
I suspect that the components that are set in the toolbar come from a template, is that correct? The setOptions() method reinitializes the grid. If the template that is used is actually a server-side template, it cannot be evaluated on the client-side. You should either create a new template, or switch to the client-side template.
Sharing the relevant code snippets for the toolbar would be helpful to me as I would provide you with accurate suggestions on how to cope with the case.
Looking forward to your reply.
Regards,
Tsvetomir
Progress Telerik

All are client side I think. Thank you again for your help!
@(Html.Kendo().Grid<
UsersList
>
()
.Name("grid")
.ToolBar(t =>
{
t.ClientTemplateId("GridToolbarTemplate");
...
<
script
id
=
"GridToolbarTemplate"
type
=
"text/x-kendo-template"
>
<
div
class
=
"menuBtnContainer"
>
<
ul
id
=
"menu"
>
<
li
>
<
a
href
=
"\\#"
class
=
"k-link k-button k-button-icon"
title
=
"Menu"
style
=
"font-family: verdana,arial,sans-serif; font-size: 12px;"
><
span
class
=
"k-icon k-i-menu"
style
=
"padding-left:3px;"
></
span
></
a
>
<
ul
>
<
li
><
span
class
=
'k-icon k-i-check'
></
span
>User List</
li
>
<
li
><
span
class
=
'menuSpace'
></
span
>Profile List</
li
>
</
ul
>
</
li
>
</
ul
>
</
div
>
<
div
class
=
"toolbar"
>
<
input
id
=
"dropdownSource"
style
=
"width:200px; display:none; font-family: verdana,arial,sans-serif; font-size: 12px;"
/>
</
div
>
<
span
class
=
"k-textbox k-grid-search k-display-flex"
style
=
"float:right"
><
input
title
=
"Search..."
class
=
"k-input"
placeholder
=
"Search..."
autocomplete
=
"off"
style
=
"font-family: verdana,arial,sans-serif; font-size: 12px;"
><
span
class
=
"k-input-icon"
><
span
class
=
"k-icon k-i-search"
></
span
></
span
></
span
>
<
div
class
=
"row"
>
</
div
>
<
div
class
=
"refreshBtnContainer"
style
=
"float:left; padding-top: 5px; margin-left:0px"
>
<
a
href
=
"\\#"
id
=
"filterIcon"
class
=
"k-button-icon"
title
=
"Refresh"
><
span
class
=
"k-icon k-i-filter"
style
=
"font-size:22px;padding-left:10px"
></
span
></
a
>
<
nav
id
=
"breadcrumb"
style
=
"float:right;"
></
nav
>
</
div
>
<!--For User Defined Filtering-->
<
div
class
=
"row"
></
div
>
<
div
id
=
"filter"
style
=
"float:left; padding-top: 5px; margin-left:0px"
>
<
div
class
=
"refreshBtnContainer"
style
=
"float:left; padding-top: 5px; font-family: verdana,arial,sans-serif; font-size: 10px;"
>
<
a
href
=
"\\#"
class
=
"k-link k-button"
title
=
"Refresh"
style
=
"font-family: verdana,arial,sans-serif; font-size: 12px;"
>Run</
a
>
</
div
>
<
div
class
=
"refreshBtnContainer"
style
=
"float:left; padding-top: 5px; padding-left: 5px; font-family: verdana,arial,sans-serif; font-size: 10px;"
>
<
a
href
=
"\\#"
class
=
"k-link k-button"
title
=
"Refresh"
style
=
"font-family: verdana,arial,sans-serif; font-size: 12px;"
>Save</
a
>
</
div
>
<
div
class
=
"refreshBtnContainer"
style
=
"float:left; padding-top: 5px;"
>
<
label
class
=
"separator-label"
for
=
"separator"
style
=
"font-family: verdana,arial,sans-serif; font-size: 20px;"
>|</
label
>
</
div
>
<
div
class
=
"refreshBtnContainer"
style
=
"float:left; padding-top: 5px; font-family: verdana,arial,sans-serif; font-size: 10px;"
>
<
a
href
=
"\\#"
class
=
"k-link k-button"
title
=
"Refresh"
style
=
"font-family: verdana,arial,sans-serif; font-size: 12px;"
>AND</
a
>
</
div
>
<
div
class
=
"refreshBtnContainer"
style
=
"float:left; padding-top: 5px; padding-left: 5px; font-family: verdana,arial,sans-serif; font-size: 10px;"
>
<
a
href
=
"\\#"
class
=
"k-link k-button"
title
=
"Refresh"
style
=
"font-family: verdana,arial,sans-serif; font-size: 12px;"
>OR</
a
>
</
div
>
<
div
class
=
"refreshBtnContainer"
style
=
"float:left; padding-top: 5px; padding-left: 5px; font-family: verdana,arial,sans-serif; font-size: 10px;"
>
<
a
href
=
"\\#"
class
=
"k-link k-button"
title
=
"Refresh"
style
=
"font-family: verdana,arial,sans-serif; font-size: 12px;"
>Add Sort</
a
>
</
div
>
<!--User Can Add as many filter he wants (ADD/OR) IN PROGRESS-->
<
div
class
=
"row"
></
div
>
<
input
id
=
"dropdownFilterItems"
style
=
"float:left; padding-top: 5px; margin-left:0px; width:180px; display:none; font-family: verdana,arial,sans-serif; font-size: 12px;"
/>
<
input
id
=
"dropdownConditionItems"
style
=
"float:left; padding-top: 5px; padding-left:5px; width:180px; display:none; font-family: verdana,arial,sans-serif; font-size: 12px;"
/>
<
div
style
=
"float:right; padding-top: 5px; padding-left:5px;"
>
<
span
class
=
"k-textbox k-grid-search k-display-flex"
><
input
title
=
"-- value --"
class
=
"k-input disabled"
placeholder
=
"-- value --"
autocomplete
=
"off"
style
=
"font-family: verdana,arial,sans-serif; font-size: 12px;"
><
span
class
=
"k-input-icon"
></
span
></
span
>
</
div
>
</
div
>
</
script
>
$(document).ready(function () {
$("#breadcrumb").kendoBreadcrumb({
items: [
{
type: "rootitem",
href: "/#",
text: "All",
showText: true,
icon: "filter",
showIcon: false
},
{
type: "item",
href: "/#",
text: "Email is not empty",
showText: true
}
],
});
$("#filterIcon").click(function () {
$("#filter").toggle();
});
$("#dropdownSource").kendoDropDownList({
dataSource: ["Users", "Contacts", "Employees"],
select: onSelectDS
});
$("#dropdownFilterItems").kendoDropDownList({
dataSource: ["Email", "First Name", "Last Name", "Status", "User Type", "Date Created", "Date Last Login"],
optionLabel: "-- choose field -- ",
});
$("#dropdownConditionItems").kendoDropDownList({
dataSource: ["starts with", "ends with ", "contains", "does not contain", "is", "is not", "is empty", "is not empty"],
optionLabel: "-- operator -- ",
});
});
Hi Ryan,
It is correct that the toolbar template will not be evaluated. What I can recommend is that you include the following option within the setOptions() method:
toolbar: [
{ template: kendo.template($("#GridToolbarTemplate").html()) }
],
Regards,
Tsvetomir
Progress Telerik

hmm there must be something. even this simple code distorts my grid header
var grid = $("#grid").data("kendoGrid");
grid.setOptions({
sortable: true
});

Also tested this one alone. Same results
function onSelectDS(e) {
if (e.dataItem) {
var dataItem = e.dataItem;
var grid = $("#grid").data("kendoGrid");
grid.setOptions({
toolbar: [
{ template: kendo.template($("#GridToolbarTemplate").html()) }
],
});
}
}
Hi Ryan,
Thank you for the provided code snippets. I suspect that the framework that is currently in use is actually ASP.NET Core, is that correct? I am asking in regards to the product that you have selected for the current support ticket - ASP.NET MVC.
Apart from rendering the toolbar template as shown below, you should reinitialize all of the widgets that are initialized in the document.ready() jQuery event. What I can recommend is that you extract those to an external function and call it in the document.ready() event and each time after using the setOptions() method.
I hope you find this helpful.
Regards,
Tsvetomir
Progress Telerik

Hi Ryan,
Attached to my response is a sample project that demonstrates how to persist the toolbar template of the Kendo UI Grid when the setOptions() method is used.
Examine it and let me know in case any additional questions arise.
Regards,
Tsvetomir
Progress Telerik

Thank you, it works!
Probably this is the last question.
.Columns(columns =>
{
columns.Select().Width(50);
columns.Bound(column => column.Email).Filterable(ftb => ftb.Multi(true).Search(true)).ClientFooterTemplate("<
input
id
=
'dropDownList'
style
=
'width:220px;font-family: verdana,arial,sans-serif; font-size: 12px;'
></
input
>").Width(250);
columns.Bound(column => column.FirstName).Filterable(ftb => ftb.Multi(true).Search(true)).Width(130);
columns.Bound(column => column.LastName).Filterable(ftb => ftb.Multi(true).Search(true)).Width(130);
})
Above are my base columns, can I add columns dynamically on serverside (OnPostRead function)?
Again, a big thanks!
Hello, Ryan,
You can add columns to the server side dynamically, however to see them, just enhance the columns object on the client as well.
var oldOptions = grid.getOptions();
oldOptions.columns = getMyNewColumns();
grid.setOptions(oldOptions);
Regards,
Alex Hajigeorgieva
Progress Telerik

Hi Alex,
Any sample code on serverside onPostRead?
I want to add in serverside coz it will be based on column fetched from different datasource. The only common column is the code from my last post.
Thanks for your help.

Hi Alex,
Below is my OnPostRead. How can I then implement adding of lastname and email column dynamically on code below. Please note that the usernumber and firstname is already added on clientside with corresponding ClientFooterTemplate for each.
Thanks!
public async Task<
JsonResult
> OnPostRead([DataSourceRequest] DataSourceRequest request, string route, string header)
{
users = new List<
UsersList
>();
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
throw new ApplicationException($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
}
string Token = await _userManager.GetAuthenticationTokenAsync(user, "T", "Token");
userData = await _restMessage.GetUsers(Token);
var uList = userData.details.value.ToList();
uList.ForEach(obj => users.Add(new UsersList
{
ProfileID = obj.userNumber,
FirstName = obj.firstName,
LastName = obj.lastName,
Email = obj.email
}));
return new JsonResult(users.ToDataSourceResult(request), new JsonSerializerSettings { ContractResolver = new DefaultContractResolver() });
}
Hi, Ryan,
I would need a little more information about the current workflow:
It seems that the data contains these properties already. If they are not in the grid columns, then you can just add them and since they are in the data, they will be rendered:
https://dojo.telerik.com/@bubblemaster/IvAvItuH
If these columns fields are not present in the data, then you would need to send them to the client side so the grid can display them. For example, you may use a standard ajax request that returns the column names and then add them to the existing columns. A similar approach is demonstrated here:
https://docs.telerik.com/kendo-ui/knowledge-base/create-with-dynamic-columns-and-data-types
Further alternatives include binding to a dynamic type:
Or using the columns AutoGenerate() method:
Regards,
Alex Hajigeorgieva
Progress Telerik

Hi Alex,
Cant seem to find any server side code here.
Reason I want to add dynamic column in serverside is that I have different datasource and the only common column is id, firstname, and lastname.
since I already put that column in clients side
.Columns(columns =>
{
columns.Select().Width(50);
columns.Bound(column => column.Email).Filterable(ftb => ftb.Multi(true).Search(true)).ClientFooterTemplate("<
input
id
=
'dropDownList'
style
=
'width:220px;font-family: verdana,arial,sans-serif; font-size: 12px;'
></
input
>").Width(250);
columns.Bound(column => column.FirstName).Filterable(ftb => ftb.Multi(true).Search(true)).Width(130);
columns.Bound(column => column.LastName).Filterable(ftb => ftb.Multi(true).Search(true)).Width(130);
})
the server side then will just add more columns on the 2 columns specified on client side.
Sample I have dropdown with values employees, relatives
If I select employees it will add employer, employer address, etc column from existing column of firstname and lastname
If I select relatives it will add relation and etc. from existing column of firstname and lastname
Will try also the link you sent
https://github.com/telerik/ui-for-aspnet-mvc-examples/blob/master/grid/grid-hierarchy-with-dynamic-model-loading-and-datatable/GridBindingToDataTable/Views/Home/Index.cshtml#L20
if it will work, but if you have serverside equivalent that something like grid.columns.add for that can be used on my
public async Task<JsonResult> OnPostRead([DataSourceRequest] DataSourceRequest request, string route, string header)
{..}
It would be much better.
Thanks Again
Hi Ryan,
My name is Tsvetomir and I am stepping in for my colleague Alex who is currently out of office.
I have investigated the correspondence so far. It is important to point out that the Telerik UI Grid for ASP.NET MVC could be bound on the server and on the client. However, mixing the two bindings is not possible.
Furthermore, the ActionMethod that you have provided - OnPostRead is used to gather and return the data for the grid in a specific format. It does not modify the initial settings of the grid. Actually, the grid does not even know about thins ActionMethod. This is due to the fact that it is initiated by the underlying data source which is decoupled from the grid.
In order to have dynamic columns, I would recommend following the suggestion of Alex's previous response, namely, the data table binding.
I hope you find those clarifications helpful.
Kind regards,
Tsvetomir
Progress Telerik