Hi All,
Just wondering on how to add a custom drop down the will do action (Item Command) for selected (checked) rows on my Kendo Grid?
Trying to mimic ServiceNow Grid, wanted to know if Kendo is capable as well.
Please see attach pic for reference.
Thanks in advance,
Ryan
1 Answer, 1 is accepted
Hi Ryan,
This functionality is not a built-in that could be configured one but it could be achieved. The steps are:
- Specify the DropDownList container as a FooterTemplate for one of the Grid's columns and initialize it with JavaScript on DataBound event of the Grid
- On Change event of the DropDownList, the selected rows could be manipulated
@(Html.Kendo().Grid<Student>()
.Name("grid")
.Columns(columns =>
{
columns.Select().Width(50);
columns.Bound(x => x.FirstName).FooterTemplate("<input id='dropDownList'></input>")});
.Events(ev => ev.DataBound("onDataBound"))
...
function onDataBound() {
$("#dropDownList").kendoDropDownList({
dataSource: ["Delete"],
optionLabel: "Select an option...",
change: change
});
}
...
function change() {
var grid = $("#grid").data("kendoGrid");
var selectedItem = grid.select();
selectedItem.each(function () {
grid.removeRow(this)
})
}
I have prepared a small demo demonstrating the above. On selecting rows from the Grid and selecting Delete from the DropDownList the selected rows are removed.
Please review it and let me know if you have any questions.
Regards,
Nikolay
Progress Telerik
Very Nice Nikolay!
This is very helpful in starting up my project.
I just have several questions though, pardon me for I'm just new in using Kendo.
I uploaded sample project here.
- I cant make excel download work
- How to remove cell border for all footer template
- Getting selected item column value so that it will be passed to my confirm
- Lastly invoke my server side code which will call api and get updated data back to grid from my dropdown change.
Thank you for your big help,
Ryan
I forgot to mention, to go to my sample grid, just click Grid menu.
Thanks again!
Hi Ryan,
Thank you for sharing your project.
I examined it and noticed that there is a missing link from the client-side resources that needs to be included in the _Layout.cshtml. Once added the Excel export works as expected:
<script src="https://kendo.cdn.telerik.com/2019.3.1023/js/jszip.min.js"></script>
<script src="https://kendo.cdn.telerik.com/2019.3.1023/js/kendo.all.min.js"></script>
<script src="https://kendo.cdn.telerik.com/2019.3.1023/js/kendo.aspnetmvc.min.js"></script>
The footer template borders could be removed with the following CSS:
.k-footer-template td {
border: none;
}
Getting the Grid table rows (or cells) which are selected could be done with select method.
Finally, as your are using remote binding you could use the read method of the dataSource to force the grid to request the servers for
Let me know if this answers your questions.
Regards,
Nikolay
Progress Telerik
Thank you Nikolay! your answer for 1 and 2 works like a charm.
Although for 3, I wanted to get the name, so that it will be included on the prompt (see attached. no attribute for name). but in the case of there are multiple selected, will just use count to be prompted which can be achieved by selectedIds.length.
For no 4, we have special case of calling rest endpoint which uses _userManager.GetAuthenticationTokenAsync and other auth that is why its on the serverside. The sample project is different from the actual, I just made use of available web api to populate the grid.
Right now still have no idea on how to invoke serverside code from the Action Dropdown footer template (Activate/Disable/Terminate). If you could provide insight on how to accomplish this, it would be a great help. I probably need the username and Action as params on the serverside and will do the api call, last item probably is how to refresh the grid with updated response from api after the put api call(Activate/Disable/Terminate) was made.
Again, thank you for your help,
Ryan
Was able to get no 3 using -> selectedItem[0].cells[2].innerText;
For no 4, I dont know if its the correct way but I just made workaround by adding 2 model vars Action and Ids and set their values on client side using jquery and called $("#myForm").submit(); to invoke public async Task<IActionResult> OnPostAsync(){....}
Just having issue with the footer dropdown though, cant set it back to selectedIndex=0 or to the optionLabel whenever they change but no record is checked on the grid.
Tried but it wont work:
$("#dropDownList")[0].selectedIndex = 0;
$("#dropDownList").prop('selectedIndex', 0);
Thanks!
Ryan
Hi Ryan,
I am glad to hear my suggestions have been helpful for you.
Regarding point 4, once an operation is performed from the dropdown, the value could be set back to the optionLabel invoking value method on the change event of the widget as shown below. Or, you might reset it at a moment convenient for you.
function change() {
var grid = $("#grid").data("kendoGrid");
var selectedItem = grid.select();
selectedItem.each(function () {
grid.removeRow(this)
})
var dropdownlist = $("#dropDownList").data("kendoDropDownList");
dropdownlist.value(0);
}
Give this a try and let me know how it works out for you.
Regards,
Nikolay
Progress Telerik
It works for me, thank you Nikolay!
Another follow up question again sorry. The solution I had using $("#myForm").submit(); to invoke public async Task<IActionResult> OnPostAsync(){....} is okay but it has draw back. Like for instance I have edited page 3 and when it reload it goes back to page1. It would be nice to save its last state or probably, I think ideally call shouldn't do postback or reload, all changes will be happening on the grid. Again if you have suggestion on calling server method on dropdown change w/o reloading or making post back just like what I have for "OnPostRead". It executes server code on pager number click but all changes only happens on the grid. All I need to pass as params is the action (selected item on dropdown) and the id's of checked grid items.
Thanks again for your help,
Ryan
Hello Ryan,
I would suggest you instead of submitting a form to perform an Ajax request. This could be done with jQuery.ajax().
Another option would be to use the query method of the DataSource. This way a page number to navigate to could be specified:
dataSource.query({
page: 3,
pageSize: 20
});
Let me know if you have any questions.
Regards,
Nikolay
Progress Telerik
Hi Nikolay,
Just wanted to ask how to use api data to populate custom dropdown for my template footer?
heres your code before;
function onDataBound()
{ $("#dropDownList").kendoDropDownList({
dataSource: ["Delete"], <- this array value will come from api call
optionLabel: "Select an option...",
change: change }); }
Thanks again in advance,
Ryan
Hi Ryan,
Remote binding for the DropDownList could be set with the transport.read configuration for the DataSource. For example:
function onDataBound() {
$("#dropDownList").kendoDropDownList({
dataTextField: "ProductName", // The field of the data item that provides the text content of the list items.
dataValueField: "ProductID", // The field of the data item that provides the value of the widget.
dataSource: {
transport: {
read: {
dataType: "jsonp",
url: "https://demos.telerik.com/kendo-ui/service/Products",
}
}
},
The above can be examined in the DropDownList Binding to remote data demo: https://demos.telerik.com/kendo-ui/dropdownlist/remotedatasource
Let me know if any further questions arise.
Regards,
Nikolay
Progress Telerik
Hi its not working for my sample below
I trying to test it from my other endpoint which returns like this kind of array [{},{},{}] . it doesn't work as well.
any idea to make it work?
$("#dropdown").kendoDropDownList({
dataTextField: "city",
dataSource: {
transport: {
read: {
dataType: "jsonp",
}
}
},
optionLabel: "Select City",
});
Hello Ryan,
Thank you for sharing the DropDownList declaration.
I noticed that the dataTextField is specifying. When dataTextField is defined, the dataValueField option also must be set.
Another thing I noticed is that the JSON that the URL returns is of type object wrapping the collection of the items and so this needs to be specified in the dataSource.schema.
Additionally, as the "city" is nestled in the location item this will be pointed in the model:
$("#dropDownList").kendoDropDownList({
dataTextField: "city",
dataValueField: "value",
dataSource: {
schema: {
data: "results",
model: {
fields: {
city: { from: "location.city" },
value: { from: "id.value" }
}
}
},
transport: {
read: {
dataType: "jsonp",
url: "https://randomuser.me/api/?results=10",
}
}
},
optionLabel: "Select City",
});
The Demo project has been updated applying the above. Please find it attached.
Let me know if you have further questions.
Regards,
Nikolay
Progress Telerik
Nice it works how about if my source is like this
[
{"userid":1, "username":"username1'},
{"userid":2, "username":"username2'},
{"userid":3, "username":"username3'},
{"userid":4, "username":"username4'},
{"userid":5, "username":"username5'}
]
Thanks again
Hi Ryan,
In case the received data is an array of objects no DataSource schema needs to be predefined:
$("#products").kendoDropDownList({
dataTextField: "username",
dataValueField: "userid",
dataSource: {
transport: {
read: {
dataType: "jsonp",
url: //url
}
}
}
});
More about Kendo DropDownList binding can be found in the following article:
I hope this helps.
Regards,
Nikolay
Progress Telerik
Hi, its showing blank. Please see code. The one without url dropdown works.
@(Html.Kendo().Grid<
UsersList
>
()
.Columns(columns =>
{
columns.Select().Width(50);
columns.Bound(column => column.Email).Filterable(ftb => ftb.Multi(true).Search(true)).ClientTemplate("#= userDetails(data) #").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)).ClientFooterTemplate("<
input
id
=
'userList'
style
=
'width:170px;font-family: verdana,arial,sans-serif; font-size: 12px;'
></
input
>").Width(195);
..
}
.Events(ev =>
{
ev.DataBound("onDataBound");
})
...
function onDataBound() {
$("#dropDownList").kendoDropDownList({
dataSource: ["Action1", "Action2", "Action3"],
optionLabel: "Actions on selected rows...",
change: change
});
$("#userList").kendoDropDownList({
dataTextField: "userId",
dataValueField: "userNumber",
dataSource: {
transport: {
read: {
dataType: "jsonp",
url: "https://restsandbox.azurewebsites.net/services/rest/gettestdata?username=test_api_user&password=Te$tUser1"
}
}
}
});
}
Anything I missed?
Thanks!
Hi Ryan,
Thank you for sharing the API used for the DropDownList binding.
The reason for the DropDownList not populating is that the response is in this format:
[{"userNumber":1613,"userId":"taa@noemail.com"},{"userNumber":1614,"userId":"tba@noemail.com"},{"userNumber":1615,"userId":"tau@noemail.com"},{"userNumber":1616,"userId":"tbu@noemail.com"},{"userNumber":1637,"userId":"Noreen@noemail.com"}]
But instead, it has to be in this format:
jQuery112409029558402791507_1584524506646([{"ProductID":1,"ProductName":"Chai","UnitPrice":18,"UnitsInStock":39,"Discontinued":false},{"ProductID":2,"ProductName":"Chang","UnitPrice":19,"UnitsInStock":17,"Discontinued":false},{"ProductID":3,"ProductName":"Aniseed Syrup","UnitPrice":10,"UnitsInStock":13,"Discontinued":false} ])
Namely, the response must be wrapped in a jQuery object when using jsonp data type. If this type is omitted it will work as you can see in the following Dojo demo:
For more information on jsonp format please refer to the following article:
Let me know if you have any questions.
Regards,
Nikolay
Progress Telerik
Hi Nikolay,
In sample https://dojo.telerik.com/oyijANoZ
the url: "https://www.mocky.io/v2/5e71ead23300000f0044c4b7" works
but if I replace it with my actual url: "https://restsandbox.azurewebsites.net/services/rest/gettestdata?username=test_api_user&password=Te$tUser1"
its not working anymore?
Hello Ryan,
When using the actual link a cross-domain request is made actually gets blocked by CORS which prevents the DropDownList from binding to the data:
What you could do here is anable CORS in your project. More about this can be found in the below articles:
- https://docs.telerik.com/kendo-ui/framework/datasource/cors
- https://www.telerik.com/blogs/supporting-cors-by-proxying-requests-with-express
Alternatively to the above, you could choose jsonp dataType, however the response must be wrapped in a callback:
Wich one of the opproached you would go for is entirely up to you and you project needs.
Regards,
Nikolay
Progress Telerik
Hello Ryan,
You are most welcome.
Let us know if anything else arises.
Regards,
Nikolay
Progress Telerik
Our thoughts here at Progress are with those affected by the outbreak.
Hi,
Just a followup question. How to add 2 default items on combo and then be populated from api data?
function onDataBound() {
$("#dropDownList").kendoDropDownList({
dataTextField: "ProductName", // The field of the data item that provides the text content of the list items.
dataValueField: "ProductID", // The field of the data item that provides the value of the widget.
dataSource: {
transport: {
read: {
dataType: "jsonp",
}
}
},
How to put 2 items on top of fetched data on code above
Thanks!
Hi Ryan,
This could be accomplished by using the dataSource add() method. Once the item is added, the DropDownList will automatically refresh. This I suggest can be performed in the open event handler of the DropDownList, for instance:
open: function (e) {
e.sender.dataSource.add({"ProductID": 123, "ProductName": "Chai2"});
}
Let me know if this answers your question.
Regards,
Nikolay
Progress Telerik
Our thoughts here at Progress are with those affected by the outbreak.
Hi Nikolay,
It works although it was added at the end of the list.
Is there a way to put it on the beginning of the list?
Also it always add the same item when i open the combobox.
How to check in if its already exist so I wont do e.sender.dataSource.add...?
Thank you so much,
Ryan
Hello Ryan,
To have the item added only once to the DropDownList I would suggest doing it after the dataSource has been loaded using requestEnd event. The unshift JavaScript method will add it to the beginning of the list:
$("#dropDownList").kendoDropDownList({
dataSource: {
requestEnd: function (e) {
var response = e.response.results
response.unshift({"Product": 123, "ProductName": "Chai"})
}
Let me know if anything further arises
Regards,
Nikolay
Progress Telerik
Our thoughts here at Progress are with those affected by the outbreak.
Wow, it works like a charm!
Thanks Nikolay
Hello Ryan,
You are most welcome and I am glad this is helping you move forward.
Please reply here in case of further inquiries or submit new threads for new ones.
Regards,
Nikolay
Progress Telerik
Our thoughts here at Progress are with those affected by the outbreak.