Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Update handsontable by editing table and/or eventReactive

I am using the rhandsontable package in a Shiny app which should have the following functionality:

  • the data used in the calculation can be randomly generated, invoked by an actionButton (and when the app starts)
  • the data can be manually edited by the user via the handsontable object
  • after manual editing it should be possible to re-generate random data, invoking a new calculation

The following app does exactly that what I want, but I could not figure it out how to get rid of the global variable did_recalc. It is a minimal example, where the data consists of two numeric values which are summed up.

library(shiny)
library(rhandsontable)

did_recalc <- FALSE

ui <- fluidPage(
  rHandsontableOutput('table'),
  textOutput('result'),
  actionButton("recalc", "generate new random vals and calculate")
)

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

  dataset_generator <- eventReactive(input$recalc, {
    df <- as.data.frame(runif(2))
    output$table <- renderRHandsontable({rhandsontable(df)})
    did_recalc <<- TRUE
    df
  }, ignoreNULL = FALSE)

  output$result <- renderText({ 
    df <- dataset_generator()
    if (!is.null(input$table) && !did_recalc) 
      df <- hot_to_r(input$table)
    did_recalc <<- FALSE
    sum(df)
  })
}) 

shinyApp(ui = ui, server = server)

If I remove the !did_recalc condition within output$result <- ... then editing the table still invokes a (correct) calculation. But if "recalc" is pressed (after some manual editing was done), then the "recalc" button just generates new random values, but without recalculating the sum.

It seems to me, that input$table can just be changed by manual edits of the table object and does not care about new values given via renderRHandsontable. Hence I need this hack with the global variable, which allows me to track if the user just re-generated the data (causing that input$table is "outdated")

Has anybody an idea how to get the functionality of this example without the global variable?

like image 838
Patrick Roocks Avatar asked Nov 15 '15 17:11

Patrick Roocks


People also ask

How do I set readonly options in handsontable?

If you use Handsontable through modules: to use an option that comes from a Handsontable plugin, import and register that plugin when initializing your Handsontable instance. In the example below, the cells option sets each cell in the first and fourth row as readOnly. Options modified through cells overwrite all other options.

How do I change the cell options in handsontable?

When Handsontable is running, you can change the initial cell options, using the setCellMeta () method. You can apply configuration options to individual grid elements (columns, rows, cells), based on any logic you implement, using the cells option.

How do I apply configuration options to a column in handsontable?

To apply configuration options to an individual column (or a range of columns), use the columns option. Within Handsontable constructor 's second argument, add an option called columns. Set the columns option to an array of objects.

What is action action in handsontable?

Action triggered by Handsontable after the loadData or updateSettings ( {data: myData}) with the data property method has been called. Action triggered by Handsontable after requesting for populating data. Action triggered by Handsontable after the column data splicing has been done.


1 Answers

You could store the data in a reactiveValues and have two observers updating it; one if the button is clicked, one if the table is edited by hand.

In your output$table and output$result, you then just need to use the data that is in the reactiveValues. Here's an example (same ui.R as you posted):

server <- function(input,output,session)({
  values <- reactiveValues(data=as.data.frame(runif(2)))

  observe({
    input$recalc
    values$data <- as.data.frame(runif(2))
  })

  observe({
    if(!is.null(input$table))
     values$data <- hot_to_r(input$table)
  })


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


  output$result <- renderText({ 
    sum(values$data)
  })
}) 
like image 102
NicE Avatar answered Oct 03 '22 15:10

NicE