select row in DataTable

4,302 views
Skip to first unread message

Cory N

unread,
Nov 20, 2013, 11:41:10 AM11/20/13
to shiny-...@googlegroups.com
I have used this... https://github.com/ksavin/SelectableRows to do selectable rows in tables in a shiny app. It's pretty simple, but requires giving a class parameter to the table.

Can I implement something like this within the DataTable structures that are now available in 0.8?

Thanks

Mikhail Lisovich

unread,
Nov 21, 2013, 12:43:13 PM11/21/13
to shiny-...@googlegroups.com
Awesome stuff! Thanks for sharing
Message has been deleted

Kirill Savin

unread,
Nov 22, 2013, 4:47:20 AM11/22/13
to shiny-...@googlegroups.com
Yes, it is possible.

The main problem with binding data tables is sorting/filters/pagination. When a user sorts table, a row number is returned from a sorted table, which makes returning row index useless. Filters and pagination do not make life any easier. The most painless solution I can think of is returning all the contents of the row, not just the row number and matching it with your data frame in R. Obviously, all entries would have to be unique.

I have attached a working example that returns an entire selected row as a character vector. You can also uncomment
//return $(tbl).children().children('.rowsSelected').index() + 1; in DTbinding.js
if you want a row number instead.

Cheers.

Updated: Made a mistake in a post above (deleted). Updated file attached
SelectableDataTables.zip

Marc Carlson

unread,
Dec 5, 2013, 2:37:13 PM12/5/13
to shiny-...@googlegroups.com
Hi Kirill,

Thanks for posting this!  It is very nearly something I would like to do.  How would I go about modifying this code so that I could select and extract multiple rows of data at a time?

 Marc

Kirill Savin

unread,
Dec 6, 2013, 7:08:13 AM12/6/13
to shiny-...@googlegroups.com
You are very welcome. Modified example for multiple selection attached.
Notes:
- Shift+click to select multiple rows one-by-one. Ctrl is reserved in dataTables for excel-like cell highlighting, I've no idea what's it for and how to disable this behavior.
- To return row indices instead of cell contents (indices would be wrong if the table is filtered or sorted), uncomment the following in DTbinding.js
//    $rows.each(function(row, v){
//      out[row] = $(v).index() + 1;
//    });
//  return out;


- If you keep returning cell contents, they would come to R as a character vector, would be easy to reshape it into matrix in R.

To all: is it possible to return a 2D array to R from JS?
SelectableDataTables.zip

Dan Tenenbaum

unread,
Dec 6, 2013, 5:03:36 PM12/6/13
to shiny-...@googlegroups.com
Hi, this is awesome!

I'm working on this with Marc and I have one more question.

Rather than send data back to R each time one or more rows is selected, I'd like to let the user select multiple rows and then click a "Send To R" button that would send all the selected rows to R.

I looked at your code and it didn't seem super trivial to make this change. It seems like you are telling shiny to pay attention to table selection events, but I'd like it instead to pay attention to the clicking of the "send to R" button which needs to know how to send back all data from selected rows to R. How do I do that?

Thanks so much for your help.
Dan

Kirill Savin

unread,
Dec 6, 2013, 6:46:22 PM12/6/13
to shiny-...@googlegroups.com
No need to modify js code for this. Create an actionButton actionButton("btnSend", "Send Rows") in R and modify the observer slightly:

  observe({
    if (input$btnSend > 0)
      print(isolate(input$myTable))
    })


Isolation FTW.

Dan Tenenbaum

unread,
Dec 6, 2013, 7:13:04 PM12/6/13
to shiny-...@googlegroups.com
It works like a charm! This is great--this is going to be really useful.

Thanks,
Dan

ZJ

unread,
Dec 6, 2013, 10:26:22 PM12/6/13
to shiny-...@googlegroups.com
This is pretty cool! Something minor though isn't the Ctrl key the traditional key for select multiple elements? While the shift key selects all elements between the first and 2nd click?

Replace the  e.shiftKey with e.ctrlKey should do the trick

Kirill Savin

unread,
Dec 6, 2013, 11:06:26 PM12/6/13
to shiny-...@googlegroups.com

Hi, ZJ. I don't know why, but ctrl+clicking on datatable draws a blue border around a clicked cell (see screen). Do you happen to know how to disable this behavior?
Shift+click selects a text in cells, but I know how to suppress it, so I ended up with Shift.

Blake Arensdorf

unread,
Feb 11, 2014, 12:07:36 PM2/11/14
to shiny-...@googlegroups.com
Kirill,

Do you by chance have a simple way to extend this and make the certain cells editable for the user?

I'd like to display a table but also let the  user override certain values if they want.

Thanks!

Vincent

unread,
Feb 11, 2014, 6:26:23 PM2/11/14
to shiny-...@googlegroups.com
I am not sure dataTable has that functionality. However, take a look at https://github.com/trestletech/shinyTable

Albert Vilella

unread,
Jul 22, 2014, 6:05:35 AM7/22/14
to shiny-...@googlegroups.com
Is there a more recent solution to this problem in DataTables?

I am interested in getting it working:

Yihui Xie

unread,
Aug 1, 2014, 11:46:55 PM8/1/14
to Albert Vilella, shiny-discuss
Yes, we are making progress on this issue. You can keep an eye on this
Github issue https://github.com/rstudio/shiny/issues/400. Here is a
quick experimental demo: http://demo.shinyapps.io/029-row-selection
Please keep in mind we still need some time before you can put this
feature in production (hopefully shiny 0.10.2 will support it).

Regards,
Yihui

Albert Vilella

unread,
Sep 10, 2014, 10:30:46 AM9/10/14
to shiny-...@googlegroups.com, avil...@gmail.com
How about selecting a few rows, then reordering by one or many columns? In the demo below, the selection disappears on reordering...

Yihui Xie

unread,
Sep 17, 2014, 5:10:30 PM9/17/14
to Albert Vilella, shiny-discuss
Good question. In that case, my demo will fail to give you correct row
indices. It was just a proof of concept. More careful work is needed
to get this accurately done.

Regards,
Yihui

Enzo

unread,
Nov 14, 2014, 4:57:12 PM11/14/14
to shiny-...@googlegroups.com, avil...@gmail.com
Great example Yihui Xie, I managed to add your example to my code.

The problem I have though is that the code gives me a relative addressing of the row, while I need to be certain of the absolute row number selected.

Is there a way to either modify your code to get the absolute row, or to get the page number (as well as the number of record per page)?

Many thanks in advance

ShinyIsCool

unread,
Dec 9, 2014, 11:26:33 AM12/9/14
to shiny-...@googlegroups.com, avil...@gmail.com
Hello!  I too have added the selectable rows example to my code base.  I preferred adding check boxes as shown here [link]

Question: how would I add a SelectAll button to this page?

Murat Tasan

unread,
Dec 9, 2014, 11:57:50 PM12/9/14
to shiny-...@googlegroups.com
I tried to roll my own roll selector by creating a custom input binding for Shiny, but I've failed so far... perhaps someone (more knowledgeable in JS and Shiny's binding registration process) would know what I might be doing wrong below?

foo.js:

var row_click_binding = new Shiny.InputBinding();
$.extend(row_click_binding, {
    find: function(scope) { return $(scope).find("#my_table tbody tr"); },
    getId: function(el) { return "my_table"; },
    getValue: function(el) { return "my_value" },
    setValue: function(el, value) { return null; },
    subscribe: function(el, callback) {
        $(el).on("click.foo", function(event) {
            console.log(this)
            callback();
        })
    },
    unsubscribe: function(el) { $(el).off(".foo"); }
})
Shiny.inputBindings.register(row_click_binding);

My understanding (which is obviously wrong) is that the register() call will register the event handlers specified in the subscribe() method.
The "click" event should trigger the row's text to appear on the JS console, but on execution it appears no event is bound to the table's rows.
I've included this file in ui.R, like so:

shinyUI(fluidPage(
    tags$head(tags$script(src = "foo.js")),
    ## rest of Shiny's layout, including the dataTableOutput() call
))

But I've also tried placing the line sourcing "foo.js" at the bottom of the fluidPage() call, thinking perhaps it was trying to bind to DOM elements that didn't exist yet, but no luck at the bottom, either.

Any ideas?

Cheers,

-Murat

Murat Tasan

unread,
Dec 10, 2014, 12:23:49 AM12/10/14
to shiny-...@googlegroups.com
For what it's worth, this exact code works just fine when I'm binding to other DOM elements, even those created by Shiny's ui.R.
For example, if I create a helpText(...) element and alter the JS find(...) function to select ".help-block", the alert modal appears on a click of the help text.
I verified, however, that "#my_table tbody tr" does indeed select all rows of the data table (via the console).
I further tried re-registering the input binding from the console after I was sure the DOM element was fully loaded, and still no responsiveness.
So somehow it appears dataTables elements are behaving differently from other elements?

Cheers,

-Murat
Reply all
Reply to author
Forward
0 new messages