Update Handsontable by Editing Table And/Or Eventreactive

Update handsontable by editing table and/or eventReactive

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

Rhsiny: Automatically update an output object based on updated rhandsontable object

Please read this. You can access the rhandsontable params via input$my_id. To get the current data use input$my_id$params$data.

Here is what I think you are after:

library(shiny)
library(rhandsontable)

ui <- fluidPage(rHandsontableOutput("contents"),
tableOutput("test_table"),
tableOutput("test_table_subset"))

server <- function(input, output) {

# dummy data
x = c('A', 'A', 'A', 'B', 'B', 'C')
y = c('G1', 'G1', 'G1', 'G2', 'G2', 'G3')
z = c('100', '200', '300', '400', '500', '600')

b = data.frame('Category' = x,
'Group' = y,
'Total' = z)

# create reactive object to be used in multiple places
test <- reactive({
t <- b # dplyr::filter(b, b$Category %in% input$cat & b$Group %in% input$group)
return(t)
})

output$contents <- renderRHandsontable({
rhandsontable(test())
})

contentsTableDat <- reactive({
req(input$contents)
hot_to_r(input$contents)
})

output$test_table <- renderTable({
contentsTableDat()
})

output$test_table_subset <- renderTable({
contentsTableDat()[1, 3]
})
}

shinyApp(ui = ui, server = server)

Shiny - Editing rhandsontable tables with multiple input and output elements

I think you were almost there. You can, however, not use an input for creating a reactive value. But this is anyways not eneded and you can initiate it with a NULL.

library(shiny)
library(rhandsontable)

ui <- fluidPage(
numericInput("x", "number of values", 2),
rHandsontableOutput('table'),
textOutput('result'),
plotOutput('plot'),
actionButton("recalc", "generate new random vals and calculate")
)


server <- function(input,output,session)({
values <- reactiveValues(data = NULL) ## assign it with NULL

## button press resets now the data frame
observeEvent(input$recalc, {
values$data$x <- 0
})

## changes in numericInput sets all (!) new values
observe({
req(input$x)
values$data <- data.frame(x = runif(input$x))
})

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


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


output$result <- renderText({
req(values$data)
sum(values$data)
})

output$plot <- renderPlot({
req(values$data)
barplot(values$data$x)
})

})

shinyApp(ui = ui, server = server)

How can I update plot from rhandsontable with uploaded data, without clicking into the table first?

In the end I did manage to get this to work by storing the data in reactiveValues and using a couple of observers. I believe that the eager evaluation of these observers was the key.

New code:

library(shiny)
library(rhandsontable)

empty_mat = matrix(1,nrow = 3, ncol = 1)
curr_names = c("EUR","GBP","CAD")
empty_dat = cbind.data.frame(curr_names,empty_mat)
names(empty_dat) = c("Currency","Values")


ui = fluidPage(sidebarLayout(
sidebarPanel(
fileInput('file1', 'Choose CSV File'),
rHandsontableOutput('contents'),
actionButton("go", "Plot Update")

),
mainPanel(
plotOutput("plot1")
)
))


server = function(input, output) {

indat <- reactiveValues(data=empty_dat)

observe({
inFile = input$file1
if (is.null(inFile))
return(NULL)
data1 = read.csv(inFile$datapath)
indat$data <- data1
})

observe({
if(!is.null(input$contents))
indat$data <- hot_to_r(input$contents)

})

output$contents <- renderRHandsontable({
rhandsontable(indat$data)
})

portfoliovals <- eventReactive(input$go, {
return(indat$data[,2])
})

output$plot1 <- renderPlot({
plot(portfoliovals()~c(1,2,3),type = "l")
})

}


shinyApp(ui, server)

R shiny: different behaviours of observeEvent and eventReactive

It's because edits() isn't called thereafter, so shiny thinks you don't need it, hence no reason to do any work on it, you need to add where it should go or what you want to do with it:

library(shiny)

ui <- fluidPage(
rhandsontable::rHandsontableOutput(
outputId = "data")
)

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

data <- data.frame(a = 1, b = 2, c = 3)

output$data <- rhandsontable::renderRHandsontable({
rhandsontable::rhandsontable(
selectCallback = TRUE,
data = data)
})

observeEvent(input$data$changes$changes, {
print("ping")
})

edits <- eventReactive(input$data$changes$changes, {
print("pong")
})

observe({
edits()
})

}

shinyApp(ui = ui, server = server)

User input in DataTable used for recalculation and update of column in Shiny

I couldn't fully understand your code so I've myself produced another reproducible example based on a bunch of other answers especially this one.

library(shiny)
library(data.table)
library(rhandsontable)

DF = data.frame(num = 1:10, qty = rep(0,10), total = 1:10,
stringsAsFactors = FALSE)
#DF = rbind(DF, c(0,0,0))

ui = fluidPage(
titlePanel("Reactive Table "),
fluidRow(box(rHandsontableOutput("table", height = 400)))
)
server = function(input, output) {

data <- reactiveValues(df=DF)



observe({
input$recalc
data$df <- as.data.frame(DF)
})

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


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




output$table <- renderRHandsontable({

data$df$total <- data$df$num * data$df$qty
print(sum(data$df$num*data$df$price) )

rhandsontable(data$df, selectCallback = TRUE)
})


}
shinyApp(ui, server)

The very first idea is to use rhandsontable which is specifically for this kind of purpose.



Related Topics



Leave a reply



Submit