Selecting multiple rows with checkboxes and shift key

8 posts, 0 answers
  1. Ryan
    Ryan avatar
    11 posts
    Member since:
    Oct 2017

    Posted 24 Sep 2018 Link to this post

    Hello,

     

    I am using columns.Select() to make my rows selectable via checkboxes.

     

    I would like to know if it is possible to use the shift key to select multiple rows as in:

    1) click the checkbox for the first row to be selected.

    2) hold the shift key down

    3) click the checkbox for the last row to be selected.

    4) programmatically select the entire range of rows between the two selected rows.

     

    Are there any demos that relate to this functionality?

     

    Thanks,

    Ryan

  2. Georgi
    Admin
    Georgi avatar
    703 posts

    Posted 26 Sep 2018 Link to this post

    Hello Ryan,

    A possible solution is to attach a click event handler to the checkbox and within that handler check whether the shift key is pressed and if it is select the range between the lastly selected row and the currently selected.

    e.g.

    $(function () {
        var lastActive;
     
        $('#grid').on('click', "tbody > tr input[data-role='checkbox'].k-checkbox", function (e) {
            var grid = $('#grid').data('kendoGrid');
            if (e.shiftKey) {
                if (!lastActive) {
                    return;
                }
     
                grid.clearSelection();
     
                var allRows = grid.items();
                var start = allRows.get().indexOf(lastActive.get()[0])
                var end = allRows.get().indexOf($(e.target).parents('tr').get()[0]);
     
                grid.select(allRows.splice(start, end - start+1));
     
            } else {
                lastActive = $(e.target).parents('tr');
            }
        })
    })

    For your convenience I am attaching a small sample which demonstrates the above approach.


    Regards,
    Georgi
    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
    11 posts
    Member since:
    Oct 2017

    Posted 02 Oct 2018 in reply to Georgi Link to this post

    Hello Georgi,

    Thank you for this post. Sorry it took me a little time to try this out, but I have now given it a try, and it is working wonderfully! This is a big relief, as this feature is actually very important to our users.

    Regards,

    Ryan

  4. Ryan
    Ryan avatar
    11 posts
    Member since:
    Oct 2017

    Posted 02 Oct 2018 Link to this post

    Hi Georgi,

    I have made a few modifications to your sample code, and am having one problem.

    • The first modification is to allow a range of rows to be selected when "end" is less than "start" (i.e. allow the selection to grow upwards, not just downwards on the grid).  This is working fine.
    • Second, in order make the grid behave more like a multiselect list box, I added code to clear any previously selected rows unless the control key or shift key is pressed.
      •  

     

    $(function () {
               var lastActive;
     
               $('#auto_gen_conn_mngr_grid').on('click', "tbody > tr input[data-role='checkbox'].k-checkbox", function (e) {
                   var grid = $("#auto_gen_conn_mngr_grid").data("kendoGrid");
                   var allRows = grid.items();
     
                   if (e.shiftKey) {
                       if (!lastActive) {
                           return;
                       }
     
                       var start = allRows.get().indexOf(lastActive.get()[0]);
                       var end = allRows.get().indexOf($(e.target).parents('tr').get()[0]);
     
                       if (end < start) {
                           var tmp = start;
                           start = end;
                           end = tmp;
                       }
     
                       grid.select(allRows.splice(start, end - start + 1));
     
                   } else {
                       lastActive = $(e.target).parents('tr');
     
                       if (!e.ctrlKey) {
                           grid.clearSelection();
                       }
     
                       var row = allRows.get().indexOf($(e.target).parents('tr').get()[0]);
                       grid.select(row);
                   }
               });
           });
  5. Ryan
    Ryan avatar
    11 posts
    Member since:
    Oct 2017

    Posted 02 Oct 2018 in reply to Ryan Link to this post

    The above post was not complete when I accidentally submitted it...

    .....Second, in order make the grid behave more like a multiselect list box, I added code to clear any previously selected rows unless the control key or shift key is pressed. 

    This is also working, HOWEVER, now if I clear the selection due to the CTRL key not being pressed, the code to reselect the current row is not working. So I have to hold CTRL to select a single row, which is not what I want. I have looked at the code under the debugger, and the row index is correct. Is there any reason why grid.select(..) following grid.clearSelection(..) would not be working?  Please see the code in the "else" block above.

     

    Thanks,

    Ryan

  6. Georgi
    Admin
    Georgi avatar
    703 posts

    Posted 04 Oct 2018 Link to this post

    Hi Ryan,

    I have debugged the modified version of the code and noticed that in the else statement the row variable is actually the index of the row - not the row itself.

    You should modify the logic as follows to pass the row to the select method - not the index:

    $(function () {
        var lastActive;
     
        $('#grid').on('click', "tbody > tr input[data-role='checkbox'].k-checkbox", function (e) {
            debugger
            var grid = $("#grid").data("kendoGrid");
            var allRows = grid.items();
     
            if (e.shiftKey) {
                if (!lastActive) {
                    return;
                }
     
                var start = allRows.get().indexOf(lastActive.get()[0]);
                var end = allRows.get().indexOf($(e.target).parents('tr').get()[0]);
     
                if (end < start) {
                    var tmp = start;
                    start = end;
                    end = tmp;
                }
     
                grid.select(allRows.splice(start, end - start + 1));
     
            } else {
                lastActive = $(e.target).parents('tr');
     
                if (!e.ctrlKey) {
                    grid.clearSelection();
                }
     
                var row = allRows.eq(allRows.get().indexOf($(e.target).parents('tr').get()[0]));
                grid.select(row);
            }
        });
    });


    Regards,
    Georgi
    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.
  7. Pankaj
    Pankaj avatar
    20 posts
    Member since:
    Mar 2015

    Posted 10 Jun 2020 in reply to Georgi Link to this post

    Can we do the same thing with kendo Multi-select with value mapper? i am using the kendo multi-select with more than 1000 rows with value mapper page size 80. when i am trying to select rows with Shift+ arrowdown key then after 80 rows it is not working and giving wrong selected items in Tagmode.single. I want below thing in multiselect.

    1) click the checkbox for the first row to be selected.
    2) hold the shift key down
    3) click the checkbox for the last row to be selected.
    4) programmatically select the entire range of rows between the two selected rows.

     

    Please find my code:

     @(Html.Kendo().MultiSelect()
                                               .Name("ddlTagAccelerometer")
                                               .HtmlAttributes(new { style = "width:100%" })                                           
                                               .DataTextField("text")
                                               .Placeholder("Please select sensor...")
                                               .DataValueField("value")
                                               .AutoBind(false)                                           
                                               .TagMode(TagMode.Single)
                                               .Enable(false)
                                               .AutoClose(false)
                                               .Filter(FilterType.Contains)
                                               .ItemTemplate("<input type='checkbox' class='multiselectcheckbox'/>  #:data.text#")
                                               .FooterTemplate("Total <strong>#: instance.dataSource.total() #</strong> items found")
                                               .TagTemplateId("tagTemplate")
                                               .Events(e => e.Change("changeMultiselect").DataBound("dataBoundMultiselect").Select("onMultiselect"))                                           
                                               .DataSource(source =>
                                               {
                                                   source.Custom()
                                                   .ServerFiltering(true)
                                                   .ServerPaging(true)
                                                   .PageSize(80)
                                                   .Type("aspnetmvc-ajax")
                                                   .Transport(transport =>
                                                   {

                                                       transport.Read(read =>
                                                       {
                                                           read.Action("GetTagAccelerometer", "Home").Data("facilityData");
                                                       });

                                                   })
                                                   .Schema(schema =>
                                                   {
                                                       schema.Data("Data").Total("Total");
                                                   });

                                               })
                                               .Height(520).Virtual(v => v.ItemHeight(32).ValueMapper("valueMapperTagAccelerometer"))
                                        )

     

     

  8. Veselin Tsvetanov
    Admin
    Veselin Tsvetanov avatar
    1241 posts

    Posted 12 Jun 2020 Link to this post

    Hi Pankaj,

    I am afraid using the same approach on a MultiSelect widget with virtualization enabled would not be possible. The reason is the elements and the data items in the widget are virtualized. That means different items will use the same DOM element depending on the exact scroll position. On the other hand, there will be cases when not all intermediate items will be present in the widget DataSource. That will make their selection impossible.

    As a side note, in case you have any further questions on a different widget, which was not part of the original question (e.g. the Grid), I would recommend you to open a separate thread for that. This way we will be able to keep each thread focused.

    Regards,
    Veselin Tsvetanov
    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