8

My R program works as expected. It shows a table containing my dataFrame, and lets me edit the values.

How do I capture those values and save them to my dataframe, or a copy of my dataframe?

require(shiny)
library(rhandsontable)

    DF = data.frame(val = 1:10, bool = TRUE, big = LETTERS[1:10],
                    small = letters[1:10],
                    dt = seq(from = Sys.Date(), by = "days", length.out = 10),
                    stringsAsFactors = F)

    rhandsontable(DF, rowHeaders = NULL)

EDIT: The above code produces a table with rows and columns. I can edit any of the rows and columns. But when I look at my dataFrame, those edits do not appear. What I am trying to figure out is what do I need to change so I can capture the new values that were edited.

PaeneInsula
  • 2,010
  • 3
  • 31
  • 57
  • Use it in a Shiny context. – hrbrmstr Mar 07 '16 at 01:56
  • I am very sorry, my cut/paste omitted the first line of my code, which set the Shiny context. I've corrected it. – PaeneInsula Mar 07 '16 at 02:37
  • So how do I go about writing a reactive widget? Any insight you can provide, or can you point me to a resource? – PaeneInsula Mar 07 '16 at 03:34
  • I do not mean to come across as offensive or harsh, but this is a _really_ straightforward thing to google or even "SO" (not sure what the shorthand for search on stackoverflow is): http://stackoverflow.com/questions/27827962/r-shiny-bi-directional-reactive-widgets – hrbrmstr Mar 07 '16 at 03:43
  • 2
    I don't think you are offensive or harsh, but I have spent the last 6 hours trying to find an answer. I know how to use a search engine (I've actually written one before), but I still cannot find anything that helps me answer this question. The reference you provide is for sliders, but after studying that I still cannot figure out how to do what I I laid out in my original post. If it would be helpful, I could post the 50+ links that I have explored and failed to find an answer. You are correct, this is a really straightforward thing to google, but finding answer still eludes me! – PaeneInsula Mar 07 '16 at 04:55

6 Answers6

5

I know this thread's been dead for years, but it's the first StackOverflow result on this problem.

With the help of this post - https://cxbonilla.github.io/2017-03-04-rhot-csv-edit/, I've come up with this:

library(shiny)
library(rhandsontable)

values <- list() 

setHot <- function(x) 
  values[["hot"]] <<- x 

DF <- data.frame(val = 1:10, bool = TRUE, big = LETTERS[1:10],
                small = letters[1:10],
                dt = seq(from = Sys.Date(), by = "days", length.out = 10),
                stringsAsFactors = FALSE)


ui <- fluidPage(
  rHandsontableOutput("hot"),
  br(),
  actionButton("saveBtn", "Save changes")
)

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

  observe({
    input$saveBtn # update dataframe file each time the button is pressed
    if (!is.null(values[["hot"]])) { # if there's a table input
      DF <<- values$hot
    }
  })

  observe({
    if (!is.null(input$hot)){
      DF <- (hot_to_r(input$hot))
      setHot(DF)
    } 
  })


  output$hot <- renderRHandsontable({ 
    rhandsontable(DF) %>% # actual rhandsontable object
      hot_table(highlightCol = TRUE, highlightRow = TRUE, readOnly = TRUE) %>%
      hot_col("big", readOnly = FALSE) %>%
      hot_col("small", readOnly = FALSE)
  })

}

shinyApp(ui = ui, server = server)

However, I don't like my solution on the part of DF <<- values$hot as I previously had problems with saving changes to the global environment. I've couldn't figure it out any other way, though.

Vesnič
  • 365
  • 5
  • 17
3

It seems to be accessible now via input$NAME_OF_rHandsontableOutput and can be converted to a data.frame via hot_to_r().

Reproducible example:

library(shiny)
library(rhandsontable)

ui <- fluidPage(
  rHandsontableOutput("hottable")  
)

server <- function(input, output, session) {
  observe({
    print(hot_to_r(input$hottable))
  })
  
  output$hottable <- renderRHandsontable({
    rhandsontable(mtcars)
  })
}

shinyApp(ui, server)
Tonio Liebrand
  • 17,189
  • 4
  • 39
  • 59
1

I was able to accomplish this with a more simple solution for saving data while the app is open and after it is closed for shiny 1.7++

Create an observe event dependent upon a save button clicked at any point when the app is open. I've scaled this method in more complex apps where you have a selectizeinput for swapping in and out different data frames into the rhandsontable, each of which are edited, saved and recalled while the app is open.

In the server:

   observeEvent(input$save, { #button is the name of the save button, change as needed
    df <<- hot_to_r(input$rhandsontable) #replace rhandsontable with the name of your own
    }) #df is the data frame that have it access when the app starts

In the UI:

actionButton("save","Save Edits")
0

I don't know what you want to recover exactly, but this seems to work:

DF <- rhandsontable(DF, rowHeaders = NULL)
library(jsonlite)
fromJSON(DF$x$data)
griverorz
  • 677
  • 5
  • 11
0

If you are using Shiny then input$table$changes$changes can give you the edited value with row and column index. Below is the code if you want to update only specific cell and not the complete table using hot_to_t().

library(shiny)
library(rhandsontable)

DF = data.frame(val = 1:10, bool = TRUE, big = LETTERS[1:10],
                small = letters[1:10],
                dt = seq(from = Sys.Date(), by = "days", length.out = 10),
                stringsAsFactors = F)



ui <- fluidPage(
  rHandsontableOutput('table')
)

server <- function(input, output) {
  
  X = reactiveValues(data = DF)

  output$table <- rhandsontable::renderRHandsontable({
    rhandsontable(X$data, rowHeaders = NULL)
  })
  
  observeEvent(input$table$changes$changes,{
    row = input$table$changes$changes[[1]][[1]]
    col = input$table$changes$changes[[1]][[2]]
    value = input$table$changes$changes[[1]][[4]]
    
    X$data[row,col] = value
})
}

shinyApp(ui, server)
Saurabh Rd
  • 46
  • 2
0

Here's an example from related post How to add columns to a data frame rendered with rhandsontable in R Shiny with an action button?, which started with Tonio Liebrand's solution above but rendered reactively with columns added by the user via action button so you can see the table evolve and see how manual edits to the table stick around:

library(shiny)
library(rhandsontable)

myDF <- data.frame(x = c(1, 2, 3))

ui <- fluidPage(rHandsontableOutput('hottable'),
                br(),
                actionButton('addCol', 'Add'))

server <- function(input, output, session) {
  EmptyTbl <- reactiveVal(myDF)
  
  observeEvent(input$hottable, {
    EmptyTbl(hot_to_r(input$hottable))
  })
  
  output$hottable <- renderRHandsontable({
    rhandsontable(EmptyTbl())
  })
  
  observeEvent(input$addCol, {
    newCol <- data.frame(c(1, 2, 3))
    names(newCol) <- paste("Col", ncol(hot_to_r(input$hottable)) + 1)
    EmptyTbl(cbind(EmptyTbl(), newCol))
    
  })
  
}

shinyApp(ui, server)
Village.Idyot
  • 1,359
  • 2
  • 8