Adding Custom drop down Item Command for Kendo Grid

1 Answer 5232 Views
Grid
Ryan
Top achievements
Rank 1
Ryan asked on 01 Dec 2019, 07:23 PM

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

Sort by
0
Accepted
Nikolay
Telerik team
answered on 03 Dec 2019, 01:49 PM

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

Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
Ryan
Top achievements
Rank 1
commented on 03 Dec 2019, 05:49 PM

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

Ryan
Top achievements
Rank 1
commented on 03 Dec 2019, 05:50 PM

I forgot to mention, to go to my sample grid, just click Grid menu.

Thanks again!

Nikolay
Telerik team
commented on 05 Dec 2019, 01:11 PM

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

Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
Ryan
Top achievements
Rank 1
commented on 06 Dec 2019, 07:10 PM

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

Ryan
Top achievements
Rank 1
commented on 08 Dec 2019, 04:49 PM

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

Nikolay
Telerik team
commented on 10 Dec 2019, 03:57 PM

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

Get quickly onboarded and successful with your Telerik UI for ASP.NET MVC with the dedicated Virtual Classroom technical training, available to all active customers.
Ryan
Top achievements
Rank 1
commented on 10 Dec 2019, 08:40 PM

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

 

 

Nikolay
Telerik team
commented on 13 Dec 2019, 08:28 AM

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

Get quickly onboarded and successful with your Telerik UI for ASP.NET MVC with the dedicated Virtual Classroom technical training, available to all active customers.
Ryan
Top achievements
Rank 1
commented on 06 Feb 2020, 11:30 AM

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

 

Nikolay
Telerik team
commented on 10 Feb 2020, 10:46 AM

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

Get quickly onboarded and successful with your Telerik UI for ASP.NET MVC with the dedicated Virtual Classroom technical training, available to all active customers.
Ryan
Top achievements
Rank 1
commented on 27 Feb 2020, 06:46 PM

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",
                            url: "https://randomuser.me/api/?results=10",
                        }
                    }
                },
                optionLabel: "Select City",
            });
Nikolay
Telerik team
commented on 02 Mar 2020, 12:59 PM

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

Get quickly onboarded and successful with your Telerik UI for ASP.NET MVC with the dedicated Virtual Classroom technical training, available to all active customers.
Ryan
Top achievements
Rank 1
commented on 11 Mar 2020, 10:51 AM

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

Nikolay
Telerik team
commented on 13 Mar 2020, 08:59 AM

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

Get quickly onboarded and successful with your Telerik UI for ASP.NET MVC with the dedicated Virtual Classroom technical training, available to all active customers.
Ryan
Top achievements
Rank 1
commented on 16 Mar 2020, 10:02 AM

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",
      }
    }
  }
});
}

 

Anything I missed?

Thanks!

Nikolay
Telerik team
commented on 18 Mar 2020, 09:50 AM

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

Get quickly onboarded and successful with your Telerik UI for ASP.NET MVC with the dedicated Virtual Classroom technical training, available to all active customers.
Ryan
Top achievements
Rank 1
commented on 18 Mar 2020, 10:06 AM

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?

Nikolay
Telerik team
commented on 20 Mar 2020, 09:12 AM

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:

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

Get quickly onboarded and successful with your Telerik UI for ASP.NET MVC with the dedicated Virtual Classroom technical training, available to all active customers.
Ryan
Top achievements
Rank 1
commented on 21 Mar 2020, 01:25 AM

Thank you!
Nikolay
Telerik team
commented on 25 Mar 2020, 06:51 AM

Hello Ryan,

You are most welcome.

Let us know if anything else arises.

Regards,
Nikolay
Progress Telerik

Progress is here for your business, like always. Read more about the measures we are taking to ensure business continuity and help fight the COVID-19 pandemic.
Our thoughts here at Progress are with those affected by the outbreak.
Ryan
Top achievements
Rank 1
commented on 16 Apr 2020, 10:52 AM

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!

Nikolay
Telerik team
commented on 20 Apr 2020, 08:20 AM

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

Progress is here for your business, like always. Read more about the measures we are taking to ensure business continuity and help fight the COVID-19 pandemic.
Our thoughts here at Progress are with those affected by the outbreak.
Ryan
Top achievements
Rank 1
commented on 20 Apr 2020, 10:58 AM

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

Nikolay
Telerik team
commented on 22 Apr 2020, 09:23 AM

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

Progress is here for your business, like always. Read more about the measures we are taking to ensure business continuity and help fight the COVID-19 pandemic.
Our thoughts here at Progress are with those affected by the outbreak.
Ryan
Top achievements
Rank 1
commented on 22 Apr 2020, 10:01 AM

Wow, it works like a charm!

Thanks Nikolay

Nikolay
Telerik team
commented on 24 Apr 2020, 06:47 AM

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

Progress is here for your business, like always. Read more about the measures we are taking to ensure business continuity and help fight the COVID-19 pandemic.
Our thoughts here at Progress are with those affected by the outbreak.
Tags
Grid
Asked by
Ryan
Top achievements
Rank 1
Answers by
Nikolay
Telerik team
Share this question
or