将Shiny应用程序中的所有用户输入导出到文件并稍后加载

Mol*_*olx 5 r shiny

我的Shiny应用程序有几个输入,用于定义生成的绘图的几个参数.用户很可能会花费几分钟时间浏览所有可能的选项,直到他对输出感到满意为止.显然,可以以不同的格式导出绘图,但是用户可能希望稍后使用不同的数据重新创建相同的绘图,或者可能只更改一个小细节.

因此,我需要为用户提供一种方法来导出他的所有设置并保留该文件供以后使用.我开发了一种方法,但效果不佳.我正在使用reactiveValuesToList获取所有输入元素的名称并将其另存为具有该格式的简单文本文件inputname=inputvalue.这是downloadHandlerserver.R:

output$bt_export <- downloadHandler(
  filename = function() {
    "export.txt"
  },
  content = function(file) {
    inputsList <- names(reactiveValuesToList(input))
    exportVars <- paste0(inputsList, "=", sapply(inputsList, function(inpt) input[[inpt]]))
    write(exportVars, file)
  })
Run Code Online (Sandbox Code Playgroud)

这工作正常,但加载不是很顺利.由于我没有(并且无法弄清楚如何)保存输入类型,我必须盲目更新这些值.我是这样做的:

importFile <- reactive({      
  inFile <- input$fileImport      
  if (is.null(inFile))
    return(NULL)      
  lines <- readLines(inFile$datapath)
  out <- lapply(lines, function(l) unlist(strsplit(l, "=")))      
  return(out)
})

observe({
    imp <- importFile()            
    for (inpt in imp) {
      if (substr(inpt[2], 0, 1) == "#") {
        shinyjs::updateColourInput(session, inputId = inpt[1], value = inpt[2])
      } else {
        try({
          updateTextInput(session, inputId = inpt[1], value = inpt[2])
          updateNumericInput(session, inputId = inpt[1], value = inpt[2])
          updateSelectInput(session, inputId = inpt[1], selected = inpt[2])              
        })
      }
    }       
  })
Run Code Online (Sandbox Code Playgroud)

除了可以从一开始就shinyjs::colorInput认识到的#,我必须try()用于其他人.这部分工作,但有些输入没有更新.手动检查导出的文件会显示未更新的输入,因此我认为一次更新100多个输入并不是一个好主意.此外try()部件看起来不太好,可能不是一个好主意.

该应用程序即将完成,但将来可能会更新,添加/更改一些输入.如果这甚至使一些"旧的"导出输入无效,这是可以接受的,因为我会尝试保持向后兼容性.但我正在寻找的方法不仅仅是编写数百行来逐个更新输入.

我想过使用save.image()但只是使用load()不恢复应用程序输入.我还考虑过以某种方式同时更新所有输入,而不是一个一个地更新所有输入,但没有提出任何结果.有没有更好的方法将所有用户输入导出到文件然后加载它们?如果对这个更好或者完全不同的方法进行调整并不重要.

Nic*_*icE 9

如果你看一下闪亮输入更新函数的代码,它们就会结束session$sendInputMessage(inputId, message).message是一个需要在输入中更改的属性列表,例如,对于复选框输入:message <- dropNulls(list(label = label, value = value))

由于大多数输入都具有value属性,因此您可以session$sendInputMessage直接在所有输入上使用该函数而无需使用try.

这是一个例子,我创建dummy_data了当你点击按钮时更新所有输入,结构应该与你导出的类似:

ui.R

library(shiny)
shinyUI(fluidPage(
  textInput("control_label",
            "This controls some of the labels:",
            "LABEL TEXT"),
  numericInput("inNumber", "Number input:",
               min = 1, max = 20, value = 5, step = 0.5),
  radioButtons("inRadio", "Radio buttons:",
               c("label 1" = "option1",
                 "label 2" = "option2",
                 "label 3" = "option3")),
  actionButton("update_data", "Update")

  ))
Run Code Online (Sandbox Code Playgroud)

server.R

library(shiny)

dummy_data <- c("inRadio=option2","inNumber=10","control_label=Updated TEXT" )

shinyServer(function(input, output,session) {
  observeEvent(input$update_data,{    
    out <- lapply(dummy_data, function(l) unlist(strsplit(l, "="))) 
   for (inpt in out) {
     session$sendInputMessage(inpt[1], list(value=inpt[2]))
    }
   })

})
Run Code Online (Sandbox Code Playgroud)

所有update函数还在调用之前预先格式化值session$sendInputMessage.我没有尝试过所有可能的输入,但至少对于这3个你可以传递一个字符串到函数来改变它numericInput,它仍然可以正常工作.

如果这是某些输入的问题,您可能希望保存reactiveValuesToList(input)使用save,并且当您想要更新输入时,使用load并运行for循环中的列表(您必须将其调整为命名列表).