Dear R-community,
I am trying to build an app with R shiny. I am using selectInput() and textInput() in cells of a table. Moreover, I want the user to be able to click a button to add a column in the table with those input fields. the problem is, that when I add a column, the entered values in the first column are saved, but not displayed, and if I re-enter some values in the first column, it doesn't change the already saved values.
I built a mock example to demonstrate my problem:
#load data
data <- data.frame(c = sample(c("A", "B"), 300, replace = TRUE), v = sample(c("w", "x"), 300, replace = TRUE), s = sample(c("FF", "GG", "HH"), 300, replace = TRUE))
data <- data[!duplicated(data),]
data <- data[order(data$c, data$v, data$s),]
numb_of_c <- length(unique(data$c))
ui <- dashboardPage(
dashboardHeader(title = "TEST",
titleWidth = 450),
dashboardSidebar(
width = 450,
sidebarMenu(
lapply(1:numb_of_c, function(i) {
menuItem(unique(data$c)[i], tabName = unique(data$c)[i])
})
)),
dashboardBody(
box(actionButton("add_col", label = "Add column"),
actionButton("rm_col", label = "Remove column"),
verbatimTextOutput("printtext")),
uiOutput("tab_items_output")
)
)
server <- function(input, output, session) {
#counter for number of columns
counter <- reactiveValues(n = 0)
observeEvent(input$add_col, {counter$n <- counter$n + 1})
observeEvent(input$rm_col, {
if (counter$n > 0) counter$n <- counter$n - 1
})
#ui for all c
output$tab_items_output <- renderUI({
theitems <- list()
for (i in 1:numb_of_c) {
theitems[[unique(data$c)[i]]] <- tabItem(tabName = unique(data$c)[i],
box(width = 12,
uiOutput(outputId = paste0("ui_", unique(data$c)[i]))
)
)
}
theitems <- unname(theitems)
do.call(tabItems, theitems)
})
#ui for each c
lapply(1:numb_of_c, function(i) {
gen_cols <- reactive({
#get data frame of current c
temp <- data[data$c==unique(data$c)[i],]
# Create selectInput and textInput objects to embed in table
table_inputs <- character(nrow(temp))
for (y in 1:(counter$n+1)) {
for (x in 1:nrow(temp)) {
if (temp$s[x]=="HH") { #if categorical
table_inputs[x] <- as.character(selectInput(paste0(as.character(temp$c[x]), as.character(temp$v[x]), as.character(temp$s[x]), y), label = NULL, choices = 1:5))
}
else {
table_inputs[x] <- as.character(textInput(paste0(temp$c[x], temp$v[x], temp$s[x], y), label = NULL, value = NULL))
}
}
temp <- cbind(temp, table_inputs)
}
temp
})
#create ui of table
output[[paste0("ui_", unique(data$c)[i])]] <- renderUI({
box(width=12,
fluidRow(dataTableOutput(outputId = paste0("table_", gen_cols()$c[i]))
)
)
})
#table ui
output[[paste0("table_", data[data$c==unique(data$c)[i],"c"][i])]] <- DT::renderDataTable(
gen_cols(),
selection = 'none',
server = FALSE,
escape = FALSE,
rownames = FALSE,
options = list(
scrollX = TRUE,
paging = TRUE,
pageLength = 100,
lengthMenu = c(5, 10, 20, 100),
preDrawCallback = JS('function() {
Shiny.unbindAll(this.api().table().node()); }'),
drawCallback = JS('function() {
Shiny.bindAll(this.api().table().node()); } '))
)
})
output$printtext <- renderPrint(print(input[["AwFF1"]]))
}
shinyApp(ui, server)
When I am entering a value of 1, I can easily access it as can be seen in the verbatimTextOutput:
When I then add a column, the 1 is still saved in the first textInput, but the textInput field is empty:
And if I try to change the value, it doesn't seem to accept any edits.
I tried to solve it somehow by including:
AllInputs <- reactive({
x <- reactiveValuesToList(input)
})
and then setting the value in the input fields, but the app kept refreshing itself:
table_inputs[x] <- as.character(textInput(paste0(temp$c[x], temp$v[x], temp$s[x], y), label = NULL, value = AllInputs()[[paste0(temp$c[x], temp$v[x], temp$s[x], y)]]))
Any help would be much appreciated!