Search code examples
rshinyshinydashboardshinyjsshinybs

using click.dt with sliders to filter after a click not updating


Please run this code. You will see when you click on a row in the datatable the number from the "a" column is plotted. That's done using callback and observeEvent. That works fine.

library(shiny)
library(DT)
runApp(shinyApp(
  ui = fluidPage(
                   DT::dataTableOutput('table')  ,
                   selectInput("NUMBER", "Number:", c(1,100,1000000),selected = 1),
                   plotOutput("p")
                   ),
  server = function(input, output, session) {

    NUMBER = reactive({
      input$NUMBER
    })

    output$table <- DT::renderDataTable({
      datatable(data.frame(a = c(85,7),b=c(444,2)), rownames = FALSE, selection = 'none', callback=

      JS("table.on('click.dt', 'tr', function() {
           var data=table.row(this).data();
           Shiny.onInputChange('rows',data[0]);
          });")
      )}
    )

    observeEvent(input$rows, {

      print( input$rows)   
      print( class( input$rows)  )
      a = as.numeric(input$rows)

      print(a)
      print(NUMBER())
      new_number = a      #THIS WORKS!!!
      #new_number = a  * as.numeric(NUMBER())    #THIS DOES NOT WORK     multiple a by the number in the slider when the SLIDER Is CHANGED

      output$p = renderPlot({

        # browser()
        plot( new_number )
      })

    })}
))

But you also see a "NUMBER" slider input. When the user changes the slider I would like the plot to update so that the plot shows a times the number selected in the slider. So:

comment out this line:

new_number = a 

and uncomment this line:

new_number = a  * as.numeric(NUMBER()) 

Now rerun the code and you will see that as you select different numbers from the slider but nothing happens. This is because

new_number = a  * as.numeric(NUMBER()) 

is inside the ObserveEvent function and the table WAS NOT clicked...just the slider was changed. So how NUMBER() be made available so that this works?

Thank you.


Solution

  • All you had to do is put an observeEvent into your observeEvent :) That way when rendering a new plot R grabs the updated input. Hope this helps !

     library(shiny)
        library(DT)
    
        runApp(shinyApp(
    
      ui = fluidPage(
        DT::dataTableOutput('table')  ,
        selectInput("NUMBER", "Number:", c(1,100,1000000), selected = 1),
        plotOutput("p")
      ),
    
      server = function(input, output, session) {
    
        NUMBER = reactive({
          input$NUMBER
        })
    
        output$table <- DT::renderDataTable({
          datatable(data.frame(a = c(85,7),b=c(444,2)), rownames = FALSE, selection = 'none', callback=
    
                      JS("table.on('click.dt', 'tr', function() {
                         var data=table.row(this).data();
                         Shiny.onInputChange('rows',data[0]);
        });")
          )}
          )
    
        observeEvent(input$rows, {
    
          print( input$rows)   
          print( class( input$rows)  )
          a = as.numeric(input$rows)
          new_number <- a
    
          observeEvent(input$NUMBER, {
    
            print(a)
            print(NUMBER())
    
            number = a  * as.numeric(NUMBER())    
    
            output$p = renderPlot({
    
              # browser()
              plot( number )
            })
    
          })
    
          output$p = renderPlot({
    
            # browser()
            plot( new_number )
    
          })
    
        })
    
        }
       ))