如何在Shiny Server中重置input变量?解决DT按钮重复点击失效问题
问题解决方案
问题原因
连续点击同一行的加减按钮时,Shiny.setInputValue传递的参数对象内容完全一致(只有固定的row_index),Shiny会判定输入值没有发生变化,因此不会重复触发observeEvent。
解决方法
在触发Shiny.setInputValue时,给传递的对象添加一个每次点击都会变化的属性(比如时间戳或随机数),确保每次点击都能让输入值产生变化,从而重复触发事件处理逻辑。同时修复原代码中一处列名大小写错误(mydata$Number应为mydata$number)。
修改后的完整代码
library(shiny) library(DT) # Define UI ui <- fluidPage( # Create DT with in-cell inputSelect dropdown DTOutput("mytable"), # Output to print reactive data frame verbatimTextOutput("verbotentext") ) # Define server server <- function(input, output, session) { # Define sample data mydata <- data.frame( Name = c("John", "Mary", "Bob"), number = 5, Age = c(25, 30, 35), Gender = c("Male", "Female", "Male"), Color = c("Red", "Green", "Blue") ) rv_mydata <- reactiveVal(mydata) # Render DT output$mytable <- renderDT({ mydata <- rv_mydata() # Add in-cell inputSelect dropdown to "Color" column mydata$Color <- paste0( "<select class='form-control' onchange='", "var index = $(this).closest(\"tr\").index();", "Shiny.setInputValue(\"mydata_color\",", "{", " row_index: index,", " new_value: $(this).val()", "});'>", "<option value='Red'", ifelse(mydata$Color == "Red", " selected", ""), ">Red</option>", "<option value='Green'", ifelse(mydata$Color == "Green", " selected", ""), ">Green</option>", "<option value='Blue'", ifelse(mydata$Color == "Blue", " selected", ""), ">Blue</option>", "</select>" ) mydata$number_actions <- paste0( "<div style='display:flex;justify-content:center;'>", "<button onclick='", "var index = $(this).closest(\"tr\").index();", "Shiny.setInputValue(\"mydata_number_minus\",", "{", " row_index: index,", " timestamp: Date.now() # 添加时间戳确保每次输入值不同", "});'>", "<</button>", "<div style='padding:0px 5px;width:20px;text-align:center;'>", mydata$number, # 修复列名大小写错误 "</div>", "<button onclick='", "var index = $(this).closest(\"tr\").index();", "Shiny.setInputValue(\"mydata_number_plus\",", "{", " row_index: index,", " timestamp: Date.now() # 添加时间戳确保每次输入值不同", "});'>", "></button>", "</div>" ) datatable(mydata, escape = FALSE, selection = "none", options = list(dom = 't', paging = FALSE, ordering = FALSE)) }) # Define reactive action triggered by in-cell inputSelect dropdown observeEvent(input$mydata_color, { row_index <- input$mydata_color$row_index + 1 new_value <- input$mydata_color$new_value mydata <- rv_mydata() mydata[row_index, "Color"] <- new_value rv_mydata(mydata) }) observeEvent(input$mydata_number_minus, { row_index <- input$mydata_number_minus$row_index + 1 mydata <- rv_mydata() mydata[row_index, "number"] <- mydata[row_index, "number"] - 1 rv_mydata(mydata) }) observeEvent(input$mydata_number_plus, { row_index <- input$mydata_number_plus$row_index + 1 mydata <- rv_mydata() mydata[row_index, "number"] <- mydata[row_index, "number"] + 1 rv_mydata(mydata) }) # Print reactive data frame output$verbotentext <- renderPrint({ rv_mydata() }) } # Run app shinyApp(ui, server)
关键修改说明
- 添加时间戳参数:在加减按钮的
onclick事件中,给Shiny.setInputValue传递的对象添加timestamp: Date.now(),每次点击生成唯一的时间戳,确保输入值每次都不同,强制触发observeEvent。 - 修复列名错误:将
mydata$Number改为mydata$number,保证按钮中间显示的数值与数据框中的列一致。
内容的提问来源于stack exchange,提问作者Jochem
相关产品推荐
相关产品推荐

