2

I am trying to create a shiny app that has a rhandsontable in it. I want rhandsontable to be able to update its values in one of its columns if the corresponding values in another column is selected/ checked. So far, I have been able to use reactive / observe events to change the output values between two objects but i am unable to wrap my head around it , i.e, how do i make once column of rhandsontable reactive to another column in the same table ?

Here is a simple example of what i am trying to build:

library(shiny)
library(rhandsontable)

ui <- fluidPage(
  rHandsontableOutput('table')

)

server <- function(input,output,session)({

  data <- data.frame(c1=c(5,10,15), c2=c(3,6,9) , diff=c(0,0,0), select= as.logical( c(FALSE,FALSE,FALSE)))

  output$table <- renderRHandsontable({
    rhandsontable(data)
  })


}) 

shinyApp(ui = ui, server = server)

So if i check the column 'Select', column 'diff' should produce the difference between column c1 & c2

Fahadakbar
  • 488
  • 1
  • 8
  • 26

1 Answers1

6

From what I understand, your goal is to do some calculation depending on the values of some other column. So if for example a box of the third column is checked, you might want to compute the difference between elements of column 1 and 2.

If you had just a data frame, that would be easy, wouldn't it? Well, this is possible using reactive values. The main idea is that you can store the rhandsontable in a data frame in the backend, modify the data frame and then render the modified data frame once again back in the handsontable.

I hope this helps:

For a more detailed example on reactive values you can see this: http://stla.github.io/stlapblog/posts/shiny_editTable.html and this : https://www.youtube.com/watch?v=BzE1JmC0F6Q&list=PL6wLL_RojB5wXR3NR3K38sIvexZ_45alY&index=3

library(rhandsontable)
library(shiny)


ui <- fluidPage(
  mainPanel(
    rHandsontableOutput("hot")
  )
)

server = function(input, output, session){

  df<- data.frame(c1=c(5,10,15), c2=c(3,6,9) , diff=c(0,0,0), select= as.logical( c(FALSE,FALSE,FALSE)))
  values <- reactiveValues(data = df)

  observe({
    if(!is.null(input$hot)){
      values$data <- as.data.frame(hot_to_r(input$hot))
      isolate(values$data[,'diff'] <- ifelse(values$data[,'select'], values$data[,'c1']-values$data[,'c2'] ,0))
      print(values$data)
      output$hot <- renderRHandsontable({
        rhandsontable(values$data)
      })
    }
  })    

  output$hot <- renderRHandsontable({
    rhandsontable(values$data)
  })

}

shinyApp(ui, server)
  • Thank you, your answer is very helpful. However, I noticed that the modifications are gone when refreshing the page. Is there a simple solution to keep the modification? Thank you – John Smith May 22 '20 at 10:01
  • 1
    Is the first `output$hot <- renderRHandsontable` redundant? If you modify values$data then the second one will get triggered anyway? – Simon Woodward Jul 19 '20 at 22:04
  • 1
    @Xiaoshi I guess you just need to actually move the command df<- data.frame(c1=c(5,10,15), c2=c(3,6,9) , diff=c(0,0,0), select= as.logical( c(FALSE,FALSE,FALSE))) outside of the server function. Probably when you refresh the page the server function reactivates the whole code including this command. If you initialise the data frame outside of the server function you want have an issue I think. – Letsios Matthaios Jul 21 '20 at 16:01
  • 1
    @SimonWoodward Yes you are right! Thanks for the comment. There was a reason why I did it like that (I had created some apps where some events were not triggered for some reason, if this additional rendering was not added in the observe event). But it has been so long since the last time I worked with Rhandsontable, that I cannot recall now. – Letsios Matthaios Jul 21 '20 at 16:08