The R Shiny code posted at the bottom allows the user to add columns to a rhandsontable table, allows manual inputs into the first row of the table, and automatically populates the non-editable second row of the table with reactive values from the linked dataframe called table2. The left-half of the below image shows how the App works.
As I point out in the right-half of the image below, there appears to be a circular dependency in passing the reactive table2 object between observers. Any ideas for how to eliminate this circular dependency?
I thought combining those two observers into a single observer, and then passing the tmpTable object between functions in that same combined observer might work, but I haven't been able to get this to work.
You'll notice that sometimes when running this code and adding a column (if you add a column, change the "Month" value in the rendered rhandsontable table, and then directly click "Add" again), the rendered rhandsontable starts flashing and locks up, due to the circular dependency of that table2 object I believe. Oddly, if you add a column, change the "Month" value, and click on a table cell before clicking "Add" again, this flashing/freeze doesn't happen. Circular dependency.
Illustrations:
Code:
library(rhandsontable)
library(shiny)
mydata <- data.frame('Col1' = c(1,1), row.names = c('Month','END'))
ui <- fluidPage(
sliderInput("dft","DFT",min=0.1,max=1,value=0.3,step=0.1),
tableOutput("table1"),
rHandsontableOutput('hottable'),
actionButton("addCol","Add")
)
server <- server <- function(input, output, session) {
dft_vector <- reactive(rep(input$dft,5))
table2 <- reactiveVal(mydata)
runOff <- reactive({
f <- function(x,y){x*(1-dft_vector()[y]/12)}
res <- Reduce(f,seq(5),init=250,accumulate=TRUE)
b <- head(res,-1)
result <- data.frame(MO=seq(5),DFT=b*dft_vector()/12,END=res[-1])
})
observeEvent(input$hottable,{table2(hot_to_r(input$hottable))})
observe({
req(runOff(), table2())
tmpTable <- table2()
tmpTable[2,] <- runOff()$END[unlist(table2()[1,])]
table2(tmpTable)
})
observeEvent(input$addCol, {
newCol <- data.frame(c(1,1))
names(newCol) <- paste0("Col",ncol(hot_to_r(input$hottable))+1)
table2(cbind(table2(),newCol))
})
output$table1 <- renderTable(runOff())
output$hottable <- renderRHandsontable({
rhandsontable(table2(),useTypes=TRUE) %>% hot_row(c(2),readOnly=TRUE)
})
}
shinyApp(ui, server)
