应用程序中的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"