使用here的帮助,我正在尝试制作一个看起来像这样的闪亮应用程序:
您可以使用selectInput
按钮添加更多这样的textInput
和Add Operation
(并使用Remove Operation
按钮将其删除)。我的代码如下:
library(shiny)
mylist <- c('boxPlot','logNorm','pca')
params <- list()
params[[1]] <- list('columns')
params[[2]] <- c()
params[[3]] <- c('column','nComp')
ui <- shinyUI(fluidPage(
sidebarPanel(
actionButton("add_btn", "Add Operation"),
actionButton("rm_btn", "Remove Operation")
),
mainPanel(uiOutput("textbox_ui"))
))
server <- shinyServer(function(input, output, session){
# Track the number of input boxes to render
counter <- reactiveValues(n = 0)
#Track the number of input boxes previously
prevcount <-reactiveValues(n = 0)
observeEvent(input$add_btn, {
counter$n <- counter$n + 1
prevcount$n <- counter$n - 1
})
observeEvent(input$rm_btn, {
if (counter$n > 0) {
counter$n <- counter$n - 1
prevcount$n <- counter$n + 1
}
})
textboxes <- reactive({
n <- counter$n
vals = c()
indexOp = c()
if (n > 0) {
# If the no. of textboxes previously where more than zero, then
#save the text inputs in those text boxes
if(prevcount$n > 0){
paramsVal <- list()
if(prevcount$n > n){
lesscnt <- n
isInc <- FALSE
}
else{
lesscnt <- prevcount$n
isInc <- TRUE
}
for(i in 1:lesscnt){
inpid = paste0("textin",i)
vals[i] = input[[inpid]]
for(j in 1:length(mylist)){
# if(strcmp(vals[i],mylist[j])){
if(vals[i]==mylist[j]){
indexOp[i] = j
break
}
}
}
if(isInc){
vals <- c(vals, mylist[1])
indexOp <- c(indexOp,1)
}
lapply(seq_len(n), function(i) {
tagList(
selectInput(
inputId = paste0("textin", i),
label = h3("Select operation"),
choices = mylist,
selected = vals[i]
),
lapply(seq_len(length(params[[indexOp[i]]])), function(j) {
textInput(inputId = paste0("params",i,"_",j),label = params[[indexOp[i]]][j],value = "Parameter")
})
)
})
}
else{
indexOp[1] = 1
lapply(seq_len(n), function(i) {
tagList(
selectInput(
inputId = paste0("textin", i),
label = h3("Select operation"),
choices = mylist,
selected = mylist[1]
),
lapply(seq_len(length(params[[indexOp[i]]])), function(j) {
textInput(inputId = paste0("params",i,"_",j),label = params[[indexOp[i]]][j],value = "Parameter")
})
)
})
}
}
})
output$textbox_ui <- renderUI({ textboxes() })
})
shinyApp(ui, server)
mylist
是用户可以选择的操作列表。 params[[i]]
包含mylist
中第i个函数将采用的参数。 indexOp
只是帮助我根据用户输入检索参数。如有需要,我们将非常乐意为您解释代码,如果是这样,请在注释中告知我。
问题
我期望的是:
我单击添加操作并获得用于选择和文本(函数和参数)的新字段。
默认功能应为boxPlot,默认textInput必须为columns
。
当我将功能从boxPlot更改为pca时,我应该获得2个textInputs。
1和2正在按预期方式发生。但是在3中,textInput不会直接更改。只有在我添加其他操作之后,它才会更改。也就是说,如果一个操作是最后一个操作,它的textInputs不会立即更改,但是我必须添加另一个操作来这样做,但是如果不是最后一个操作,它们会立即更改。
我希望它像后一种情况一样工作,即,无论操作是否最后,它们都会立即更改。我怎样才能做到这一点?谢谢...
答案 0 :(得分:0)
并欢迎来到奇妙而强大的世界;)
我不喜欢给出完整的答案。但是我最近做了类似的事情。因此,这里有一些提示:
*我建议您将代码分成几部分。最近,我在使用大型Shiny模块时遇到了一些问题,并将其切成碎片(并使用(this)[https://www.r-bloggers.com/the-shiny-module-design-pattern/]编写抽象模块)确实很有帮助。
*另外,请检查以下功能:do.call()
,switch()
用于不同情况,formals()
检查功能自变量(有助于编写其余部分)。
我可能最好将其写为评论(让我知道,我还不十分习惯),但是提供良好的实践似乎比给出完整的答案更重要。
请尽情享受,让我知道我是否很好地理解了您的问题。