Adding Custom drop down Item Command for Kendo Grid

28 posts, 2 answers
  1. Ryan
    Ryan avatar
    91 posts
    Member since:
    Aug 2012

    Posted 01 Dec 2019 Link to this post

    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

     

     

     

     

  2. Answer
    Nikolay
    Admin
    Nikolay  avatar
    264 posts

    Posted 03 Dec 2019 Link to this post

    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.
  3. Ryan
    Ryan avatar
    91 posts
    Member since:
    Aug 2012

    Posted 03 Dec 2019 in reply to Nikolay Link to this post

    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

  4. Ryan
    Ryan avatar
    91 posts
    Member since:
    Aug 2012

    Posted 03 Dec 2019 in reply to Ryan Link to this post

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

    Thanks again!

  5. Nikolay
    Admin
    Nikolay  avatar
    264 posts

    Posted 05 Dec 2019 Link to this post

    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.
  6. Ryan
    Ryan avatar
    91 posts
    Member since:
    Aug 2012

    Posted 06 Dec 2019 in reply to Nikolay Link to this post

    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

  7. Ryan
    Ryan avatar
    91 posts
    Member since:
    Aug 2012

    Posted 08 Dec 2019 Link to this post

    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

  8. Nikolay
    Admin
    Nikolay  avatar
    264 posts

    Posted 10 Dec 2019 Link to this post

    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.
  9. Ryan
    Ryan avatar
    91 posts
    Member since:
    Aug 2012

    Posted 10 Dec 2019 in reply to Nikolay Link to this post

    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

     

     

  10. Nikolay
    Admin
    Nikolay  avatar
    264 posts

    Posted 13 Dec 2019 Link to this post

    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.
  11. Ryan
    Ryan avatar
    91 posts
    Member since:
    Aug 2012

    Posted 06 Feb 2020 in reply to Nikolay Link to this post

    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

     

  12. Nikolay
    Admin
    Nikolay  avatar
    264 posts

    Posted 10 Feb 2020 Link to this post

    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.
  13. Ryan
    Ryan avatar
    91 posts
    Member since:
    Aug 2012

    Posted 27 Feb 2020 in reply to Nikolay Link to this post

    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",
                });
  14. Nikolay
    Admin
    Nikolay  avatar
    264 posts

    Posted 02 Mar 2020 Link to this post

    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.
  15. Ryan
    Ryan avatar
    91 posts
    Member since:
    Aug 2012

    Posted 11 Mar 2020 in reply to Nikolay Link to this post

    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

  16. Nikolay
    Admin
    Nikolay  avatar
    264 posts

    Posted 13 Mar 2020 Link to this post

    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.
  17. Ryan
    Ryan avatar
    91 posts
    Member since:
    Aug 2012

    Posted 16 Mar 2020 in reply to Nikolay Link to this post

    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!

  18. Nikolay
    Admin
    Nikolay  avatar
    264 posts

    Posted 18 Mar 2020 Link to this post

    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.
  19. Ryan
    Ryan avatar
    91 posts
    Member since:
    Aug 2012

    Posted 18 Mar 2020 in reply to Nikolay Link to this post

    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?

  20. Nikolay
    Admin
    Nikolay  avatar
    264 posts

    Posted 20 Mar 2020 Link to this post

    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.
  21. Ryan
    Ryan avatar
    91 posts
    Member since:
    Aug 2012

    Posted 20 Mar 2020 in reply to Nikolay Link to this post

    Thank you!
  22. Nikolay
    Admin
    Nikolay  avatar
    264 posts

    Posted 25 Mar 2020 Link to this post

    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.
  23. Ryan
    Ryan avatar
    91 posts
    Member since:
    Aug 2012

    Posted 16 Apr 2020 in reply to Nikolay Link to this post

    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!

  24. Nikolay
    Admin
    Nikolay  avatar
    264 posts

    Posted 20 Apr 2020 Link to this post

    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.
  25. Ryan
    Ryan avatar
    91 posts
    Member since:
    Aug 2012

    Posted 20 Apr 2020 in reply to Nikolay Link to this post

    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

  26. Answer
    Nikolay
    Admin
    Nikolay  avatar
    264 posts

    Posted 22 Apr 2020 Link to this post

    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.
  27. Ryan
    Ryan avatar
    91 posts
    Member since:
    Aug 2012

    Posted 22 Apr 2020 in reply to Nikolay Link to this post

    Wow, it works like a charm!

    Thanks Nikolay

  28. Nikolay
    Admin
    Nikolay  avatar
    264 posts

    Posted 24 Apr 2020 Link to this post

    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.
Back to Top