4

I am trying to create my first Shiny R application, which does two things:

  1. Display user uploaded CSV file
  2. Count user selected rows

To achieve these features, I need to combine two examples file upload and row selection, which involves switching renderTable to renderDataTable. However, I am only able to display the data using renderDataTable, but not be able to pass arguments like callback and options into it.

Here is the server.R code

shinyServer(function(input, output) {
  output$contents <- renderDataTable({
    inFile <- input$file1
    if (is.null(inFile))
        return(NULL)
    subset(read.csv(inFile$datapath, header=input$header, sep=input$sep, quote=input$quote), select=input$show_vars)
  })
})

If I change the above function this case (below), I got the following errors server.R:9:5: unexpected 'if'. I think this is related to building a reactive file upload application, which I could not find good examples... Can anyone give me some suggestions? Thanks!

shinyServer(function(input, output) {
  output$contents <- renderDataTable(
    inFile <- input$file1
    if (is.null(inFile))
      return(NULL)
   subset(read.csv(inFile$datapath, header=input$header, sep=input$sep, quote=input$quote), select=input$show_vars),
   options = list(pageLength = 10),
   callback = "function(table) {
         table.on('click.dt', 'tr', function() {
           $(this).toggleClass('selected');
           Shiny.onInputChange('rows',
                               table.rows('.selected').indexes().toArray());
         });
       }"
  )
})
Community
  • 1
  • 1
TTT
  • 4,354
  • 13
  • 73
  • 123

1 Answers1

2

The first argument to renderDataTable should be an expression. You need to wrap your code in curly braces to pass this first section of code as an expression:

shinyServer(function(input, output) {
  output$contents <- renderDataTable({
    inFile <- input$file1
    if (is.null(inFile))
      return(NULL)
    subset(read.csv(inFile$datapath, header=input$header, sep=input$sep, quote=input$quote), select=input$show_vars)
  }
  , options = list(pageLength = 10),
  , callback = "function(table) {
         table.on('click.dt', 'tr', function() {
           $(this).toggleClass('selected');
           Shiny.onInputChange('rows',
                               table.rows('.selected').indexes().toArray());
         });
       }"
  )
})
jdharrison
  • 30,085
  • 4
  • 77
  • 89
  • Thanks it works well. I think my next step is to modify the callback function. Is there any reference books on wrapping JavaScript functions in Shiny R? (or I guess it would be much easier of using jQuery to modify the DOM). – TTT Nov 11 '14 at 05:49
  • I think the current javascript looks ok to count the user selected rows. A shiny variable `input$rows` will now be available in `server.R`. It is a vector containing the index of the user selected rows. The number of user selected rows will then be `length(input$rows)`. – jdharrison Nov 11 '14 at 05:54
  • Yes, I agree. But my data has a column named "study", which has multiple records. So I need to select all the records within the same study. I can easily do this in jQuery, but need to figure out the solution inside Shiny R. Thanks. – TTT Nov 11 '14 at 05:59