The below R Shiny code generates 3 linked user input tables using package rhandsontable
: the first, base_input
, allows the user to make static inputs and the next 2 user input tables, var_1_input
and var_2_input
(collectively, "var_x_input"), are reactively fed values from base_input
and the slider input (input$periods
) for time horizon, and allow the user to alter the time dimension in their respective left-most user input columns labeled "X". The image below shows the data flows.
Note that the first cell of base_input
links to var_1_input
, and the second cell of base_input
links to var_2_input
. I am trying to delink the var_x_input objects from each other, where a change in the first cell of base_input
only resets var_1_input
and a change in the second cell of base_input
only resets var_2_input
. As the below code currently and incorrectly works, if any of the var_x_input tables has been expanded by the user with values inserted, and if any of the base_input
values are changed, then both of the var_x_input tables are reset. Only the linked var_x_input table should have reset. The below diagram shows the issue. Any suggestions for how to resolve this?
Code:
library(shiny)
library(rhandsontable)
ui <- fluidPage(
sliderInput("periods", "Time window (W):", min = 1, max = 10, value = 5),
h5(strong("Variable (Y) over window (W):")),
rHandsontableOutput("base_input"),
uiOutput("Vectors")
)
server <- function(input, output, session) {
numVars <- 2 # Number of variables to model
baseValues <- reactiveValues(data = rep(20, numVars))
output$base_input <- renderRHandsontable({
rhandsontable(
data.frame(Inputs = baseValues$data),
readOnly = FALSE,
colHeaders = c('Inputs'),
rowHeaders = paste0("Var ", LETTERS[1:numVars]),
contextMenu = FALSE
)
})
observeEvent(input$base_input, {
baseValues$data <- hot_to_r(input$base_input)$Inputs
})
output$Vectors <- renderUI({
lapply(1:numVars, function(i) {
varInputId <- paste0("var_", i, "_input")
list(
h5(strong(paste("Adjust Var ", LETTERS[i], " (Y) at time X:"))),
rHandsontableOutput(varInputId)
)
})
})
lapply(1:numVars, function(i) {
output[[paste0("var_", i, "_input")]] <- renderRHandsontable({
if (!is.null(input$base_input)) {
data <- hot_to_r(input$base_input)
rhandsontable(
data.frame(X = input$periods, Y = data$Inputs[i]),
readOnly = FALSE,
rowHeaders = NULL,
colHeaders = c("X", "Y"),
contextMenu = TRUE
)
}
})
})
}
shinyApp(ui, server)
This seems to work. I use a reactive value for each value in the Inputs
column.
library(shiny)
library(rhandsontable)
ui <- fluidPage(
sliderInput("periods", "Time window (W):", min = 1, max = 10, value = 5),
h5(strong("Variable (Y) over window (W):")),
rHandsontableOutput("base_input"),
uiOutput("Vectors")
)
server <- function(input, output, session) {
numVars <- 2 # Number of variables to model
baseValues <- reactiveValues(data = rep(20, numVars))
output$base_input <- renderRHandsontable({
rhandsontable(
data.frame(Inputs = baseValues$data),
readOnly = FALSE,
colHeaders = c('Inputs'),
rowHeaders = paste0("Var ", LETTERS[1:numVars]),
contextMenu = FALSE
)
})
IndividualValues <- replicate(numVars, reactiveVal(), simplify = FALSE)
observeEvent(input$base_input, {
values <- hot_to_r(input$base_input)$Inputs
baseValues$data <- values
lapply(1:numVars, function(i) {
IndividualValues[[i]](values[i])
})
})
output$Vectors <- renderUI({
lapply(1:numVars, function(i) {
varInputId <- paste0("var_", i, "_input")
list(
h5(strong(paste("Adjust Var ", LETTERS[i], " (Y) at time X:"))),
rHandsontableOutput(varInputId)
)
})
})
lapply(1:numVars, function(i) {
output[[paste0("var_", i, "_input")]] <- renderRHandsontable({
y <- IndividualValues[[i]]()
if (!is.null(y)) {
rhandsontable(
data.frame(X = input$periods, Y = y),
readOnly = FALSE,
rowHeaders = NULL,
colHeaders = c("X", "Y"),
contextMenu = TRUE
)
}
})
})
}
shinyApp(ui, server)