Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
516 views
in Technique[技术] by (71.8m points)

r - 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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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)
  })
}) 

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...