2014-12-28 57 views
3

在我闪亮的应用程序中,我有一个使用renderUI的动态输入。如何删除闪亮的renderUI中的输入?

这很有效,程序的另一部分捕获滑块的输入。

当应用程序更改状态时(例如按下按钮“更新模型”时)我仍然需要显示/使用具有相似标签的滑块,但由于它们是“新”,需要将值重新初始化为零。

问题是滑块有内存。如果我重新使用相同的输入ID

paste0(Labv[i], "_v",buttn) 

闪亮将具有与之相关的旧值。

目前我的代码使用变量buttn绕过这个问题:每次状态改变时,我创建“新”滑块。

另一方面,用户使用应用程序的次数越多,收集到的垃圾越多。

我试图用renderUI要素的列表发送到NULL,与发送的

updateTextInput(session, paste0(lbs[i],"_v",buttn), 
      label = NULL, value = NULL) 

tags$div("foo", NULL)清单,但在每种情况下的实际变量被渲染为文本,这是最糟糕的尝试!

# Added simplified example 
library(shiny) 
library(data.table) 

# 
dt_ = data.table(Month = month.abb[1:5], 
A=rnorm(5, mean = 5, sd = 4), 
B=rnorm(5, mean = 5, sd = 4), 
C=rnorm(5, mean = 5, sd = 4), 
D=rnorm(5, mean = 5, sd = 4), 
E=rnorm(5, mean = 5, sd = 4)) 

dt_[,id :=.I] 
dt <- copy(dt_) 
setkey(dt_, "Month") 
setkey(dt, "Month") 

shinyApp(
    ui = fluidPage(
fluidRow(
    column(4, 
    actionButton("saveButton", "Update Model"))), 
fluidRow(
    column(6, dataTableOutput('DT')), 
    column(3, br(),br(),checkboxGroupInput("pick",h6("Picker"), 
    month.abb[1:5])), 
    column(3, uiOutput('foo'))), 
fluidRow(
    column(4, verbatimTextOutput('vals')))  
), 

    server = function(session,input, output) { 
    valPpu <- reactiveValues() 

    valPpu$buttonF <- 1 
    valPpu$dt_ <- dt_ 
## 
    output$DT <- renderDataTable({ 
    if(length(input$pick) > 0) { 
# browser() 
    isolate({ labs <- input$pick }) # 
    buttn <- valPpu$buttonF 

    iter <- length(labs) 
    valLabs <- sapply(1:iter, function(i) { 
      as.numeric(input[[paste0(labs[i],"_v",buttn)]]) }) 

    if(iter == sum(sapply(valLabs,length))) {   

      cPerc <- valLabs 
      cPerc <- as.data.table(cPerc) 
      cPercDt <- cbind(Month=labs,cPerc) 

      ival <- which(dt[["Month"]] 
       %in% cPercDt[["Month"]]) 
      setkey(cPercDt, "Month") 
      for(j in LETTERS[1:5]) set(dt_, i=ival, 
      j=j, dt[cPercDt][[j]] * (1 + dt_[cPercDt][["cPerc"]])) 
      valPpu$dt_ <- dt_ 
    } } 

    dt_[order(id),] 
    }, options = list(
    scrollX = TRUE, 
    scrollY = "250px" , 
    scrollCollapse = TRUE, 
    paging = FALSE, 
    searching = FALSE, 
    ordering = FALSE) 
) 
## 
    output$foo <- renderUI({ 
    if(is.null(input$saveButton)) { return() } 
    if(length(input$pick) > 0) { 
     labs <- input$pick 
     iter <- length(labs) 
     buttn <- isolate(valPpu$buttonF) 
     valLabs <- sapply(1:iter, function(i) { 
     if(is.null(input[[paste0(labs[i],"_v",buttn)]])) { 
       0 
     } else { as.numeric(input[[paste0(labs[i],"_v",buttn)]]) } 
     }) 
    # 
    toRender <- lapply(1:iter, function(i) { 
    sliderInput(inputId = paste0(labs[i], "_v",buttn), 
       label = h6(paste0(labs[i],"")), 
       min = -1, 
       max = 1, 
       step = 0.01, 
       value = valLabs[i], 
       # format = "##0.#%", 
       ticks = FALSE, animate = FALSE) 
       }) 

     toRender 
    } 
    }) 


    observe({ 

    if(is.null(input$saveButton)) { return() } 
    if(input$saveButton < valPpu$buttonF) { return() } 
    valPpu$buttonF <- valPpu$buttonF + 1 
    dt <<- valPpu$dt_ 
# TODO: add proper saving code 
}) 
    } 
) 

在实际应用中checkboxGroupInput也从服务器驱动,renderUI并按下“更新模式”时复位。另外,UI中还有更多的“事件”没有添加到代码中。

有什么想法?

+0

您是否真的必须在示例中使用data.table包?如果一个简单的数据框架有效,请在下次排除不相关的软件包。 –

+0

@yihui我使用data.table为我的应用程序和最快捷的方式为您提供一个例子是做一些剪切和粘贴。谢谢你的耐心。 – Enzo

回答

0

所以你目前的做法其实工程。 FWIW,滑块已从HTML中删除,因此您不必担心这一点。对于存储在input中的旧值,如input[['Jan_v1']],当按钮被点击两次(并且您只需要input[['Jan_v2']])时,我不明白为什么您非常关心它们,除非您的总内存少于几千字节,因为您只需要几个字节来存储这些值。你可能无法从input中删除这些值,但我建议你不要在这个问题上花费时间,直到它成为一个真正的问题。

+0

添加了一段简单的代码,以更好地解释 – Enzo

+0

之后你会如此善意地阐述“滑块已从HTML中删除”吗?另一方面,请考虑我的担心源于这样的事实:在真实场景中,我希望用户在应用上工作一个小时或更长时间,并按下“更新模型”按钮的负载。另一方面,如果你认为即使在创建“很多”这样的数据输入的情况下也不会破坏任何东西,我很满意。谢谢您的帮助。 – Enzo

+1

当然。我的意思是在你点击按钮后,旧的滑块已经在HTML中被删除,并且新的滑块被生成。您可以在JavaScript控制台中用$('#Jan_v1')'验证它:在您第一次选择第一个复选框后,此元素存在;然后你点击按钮,再次运行JS代码,你会发现它已经消失了;生成的是一个ID为“Jan_v2”的滑块。 –