应用程序中的setInputValue仅在文本输出中响应,而不在observeEvent中响应

应用程序中的setInputValue仅在文本输出中响应,而不在observeEvent中响应,r,shiny,shinyjs,R,Shiny,Shinyjs,我正在构建一个应用程序,该应用程序应该能够存储用户在仪表板中输入的位置(以便跨会话的其他用户可以关联到相同的数据)。我使用一个闪亮的应用程序,它有一个用户可以点击的操作按钮('save')。数据保存在服务器上的CSV文件中,其他用户可以使用reactiveFileReader加载该数据 这些位置分为两个块:一个块用于当前位置集,另一个块用于此会话中添加的位置(保存前)。如果用户点击“保存”按钮,将删除属于添加位置的所有输入,并调用文件读取器,这样这些位置现在就成为当前位置集的一部分 现在我的问题

我正在构建一个应用程序,该应用程序应该能够存储用户在仪表板中输入的位置(以便跨会话的其他用户可以关联到相同的数据)。我使用一个闪亮的应用程序,它有一个用户可以点击的
操作按钮('save')。数据保存在服务器上的CSV文件中,其他用户可以使用
reactiveFileReader
加载该数据

这些位置分为两个块:一个块用于当前位置集,另一个块用于此会话中添加的位置(保存前)。如果用户点击“保存”按钮,将删除属于添加位置的所有输入,并调用文件读取器,这样这些位置现在就成为当前位置集的一部分

现在我的问题是:如果我添加一个位置,点击保存按钮,然后再次尝试添加一个位置,应用程序就会崩溃。即使在我的应用程序底部的
renderText
中,
ActionButton
的值为0,但如果我调试会话,错误显然与未重置的
ActionButton
有关(值为2,但应为1)。这怎么可能

如果有什么不清楚的地方,请告诉我

我使用了闪亮的1.6.0、R4.0.3和ShinyJS2.0.0

请参阅下面的“我的代码”和CSV文件

library(shiny)
library(shinyjs)
library(shinydashboard)


# User interface for the locations input
TestUI <- function(id) {
  ns <- NS(id)
  
  fluidPage(
    
    useShinyjs(),
    
    # Action button to save the parameters ----
    actionButton(inputId = ns("save"),
                 label = "Save locations"),
    
    # Input: Text field and action button to add test street ----
    textInput(inputId = ns("location_name"),
              label = "Location name:"),
    actionButton(inputId = ns("add_location"),
                 label = "Add location"),
    div(id='add'),
    
    # User interface for already existing locations ----
    uiOutput(outputId = ns("locations")),
    
    # User interface for the locations that are added by the user ----
    uiOutput(outputId = ns("locations_added")),
    
    # textoutput
    textOutput(outputId = ns("counter"))
  )
}

# Server side for the locations input
TestServer <- function(id) {
  moduleServer(
    id,
    function(input, output, session) {
      
      # Create namespace functions
      ns <- session$ns
      
      # Set the filenames
      fn_locations <- "store/populations.csv"
      
      # What is the last time this file was saved and load the file
      input_matrix <- reactiveFileReader(5000, session, fn_locations, read.csv2)
      
      # Store the names of the locations
      location_names <- reactiveValues()
      
      # Add input fields for the already existing locations from the file
      output$locations <- renderUI({
        
        if(nrow(input_matrix()) > 0){
          
          input_list <- lapply(1:nrow(input_matrix()), function(i) {
            
            location_names[[paste0(i)]] <- input_matrix()[i,1]
            
            wellPanel(
              fluidRow(
                column(12, titlePanel(input_matrix()[i,1]))
              ),
              fluidRow(
                column(2,                 
                       numericInput(inputId = ns(paste0("population_", i)),
                                    label = "Population",
                                    min = 0,
                                    step = 1,
                                    value = input_matrix()[i,2])),
                column(1,
                       checkboxInput(inputId = ns(paste0("save_", i)),
                                     label = "Opslaan",
                                     value = TRUE))
              )
            )
          })
        } else{
          input_list <- list(wellPanel(tags$h4("No locations have been saved")))
        }
        
        do.call(tagList, input_list)
      })
      
      # List for the UI's with the added locations
      added_input_list <- list()
      
      # Add an UI for a new location ----
      observeEvent(input$add_location, {
        
        if(input$add_location > 0){
          
          input_list <- lapply(1:input$add_location, function(i) {
            
            if(i == input$add_location){
              location_names[[paste0(nrow(input_matrix()) + i)]] <- input$location_name
            }
            
            wellPanel(
              fluidRow(
                column(12, titlePanel(location_names[[paste0(nrow(input_matrix()) + i)]])
                ),
                fluidRow(
                  column(2,                 
                         numericInput(inputId = ns(paste0("population_",nrow(input_matrix()) + i)),
                                      label = "Population",
                                      min = 0,
                                      step = 1,
                                      value = ifelse(i == input$add_location, 0, input[[paste0("population_", nrow(input_matrix()) + i)]]))),
                  column(1,
                         checkboxInput(inputId = ns(paste0("save_", nrow(input_matrix()) + i)),
                                       label = "Opslaan",
                                       value = ifelse(i == input$add_location, TRUE, input[[paste0("save_", nrow(input_matrix()) +  i)]])))
                )
              )
            )
          })
          
          output$locations_added <- renderUI({
            do.call(tagList, input_list)
          })
        }
      })
      
      observeEvent(input$save, {
          # Which elements should be saved?
          savers <- sapply(paste0("save_", 1:(nrow(input_matrix()) + input$add_location)), function(x) input[[x]])
          
          to_write_matrix <- matrix(data = NA, nrow = sum(savers), ncol = 2)
          i <- 1
          j <- 1
          
          while(i <= sum(savers)){
            
            # Only save the rows for which the save option was TRUE
            if(input[[paste0("save_",j)]]){
              row_i <- c(location_names[[paste0(j)]],
                         input[[paste0("population_", j)]])
              
              to_write_matrix[i, ] <- row_i
              i <- i + 1
            }
            j <- j + 1
          }
          
          while(i <= length(reactiveValuesToList(location_names))){
            
            # Use shinyJS to remove these inputs starting from i
            runjs(paste0("Shiny.setInputValue('",ns(paste0("population_",i)),"',null)"))
            runjs(paste0("Shiny.setInputValue('",ns(paste0("save_",i)),"',null)"))
            i <- i + 1
          }
          
          # Write the locations to a file
          write.csv2(to_write_matrix, file = fn_locations, row.names=FALSE)
          
          # Remove the old added locations
          runjs(paste0("Shiny.setInputValue('",ns("add_location"),"',0)"))
          output$locations_added <- NULL
          
          # Show notification that the save was successfull
          showNotification("The locations have been saved")
      })
      
      output$counter <- renderText(input$add_location)
    }
  )
}

ui <- dashboardPage(
  
  dashboardHeader(title = "Dashboard"),
  dashboardSidebar(
    sidebarMenu(
      menuItem("Dashboard", tabName = "Dashboard", icon = icon("signal"))
    )
  ),
  dashboardBody(
    
    tabItems(
      tabItem(tabName = "Dashboard", TestUI(id = "locations"))
    )
  ),
  
  useShinyjs()
)

server <- function(input, output, session) {
  
  TestServer("locations")
}

shinyApp(ui, server)

请附上您正在加载的csv文件,它就在那里,在帖子的底部:我强烈建议将数据存储在数据库(如SQLite)中,而不是文本文件中。如果两个用户同时访问一个文本文件,则可能会发生损坏。数据库就是用来处理这个问题的。我知道,我真正的应用程序确实有一个SQLite数据库来存储数据。这看起来不像是一个最小的可复制的例子。
"V1";"V2"
"Amsterdam";"800000"
"Brussels";"700000"
"Berlin";"1500000"