简体   繁体   English

textInput没有以闪亮的方式生成

[英]textInput not generating reactively in shiny

Using help from here , I'm trying to make a shiny app that looks like: 使用此处的帮助,我正在尝试制作一个看起来像这样的闪亮应用程序:

在此处输入图片说明 You can add more such selectInput and textInput using the Add Operation button (and delete them using Remove Operation button). 您可以使用“ Add Operation按钮添加更多此类selectInputtextInput (并使用“ Remove Operation按钮将其Remove Operation )。 My code goes as: 我的代码如下:

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 is the list of operations the user can choose from. mylist是用户可以选择的操作列表。 params[[i]] contains the arguments that the i-th function in mylist would take. params[[i]]包含mylist第i个函数将采用的参数。 indexOp just helps me retrieve the arguments based on the user input. indexOp只是帮助我根据用户输入检索参数。 Would be more than happy to explain the code even more if needed, please let me know as a comment if that's the case. 如有需要,我们将非常乐意为您解释代码,如果是这样,请告诉我作为评论。

The issue 问题

What I expect from it is that: 我的期望是:

  1. I click on add operation and get new fields for select and texts (function and argument). 我单击添加操作,并获得用于选择和文本(函数和参数)的新字段。

  2. Default function should be boxPlot, and default textInput must be for columns . 默认函数应为boxPlot,默认textInput必须为columns

  3. When I change the function from say boxPlot to pca, I should get 2 textInputs. 当我将功能从boxPlot更改为pca时,我应该得到2个textInputs。

1 and 2 are happening as expected. 1和2正在按预期方式进行。 But in 3, the textInput is not changed directly. 但是在3中,textInput不会直接更改。 It changes only after I add another operation after that. 只有在我添加其他操作之后,它才会更改。 That is, if a operation is last, its textInputs don't change instantly but I have to add another operation to do so, but if it is not the last, they change instantly. 也就是说,如果一个操作是最后一个操作,它的textInputs不会立即更改,但是我必须添加另一个操作来执行此操作,但是如果不是最后一个操作,则它们会立即更改。

I want it work like the latter case, ie, they change instantly irrespective of whether the operation is last or not. 我希望它像后一种情况一样工作,即,无论操作是否最后,它们都会立即更改。 How can I do that? 我怎样才能做到这一点? Thanks... 谢谢...

and welcome in the wonderful and all-powerful world of Shiny ;) 并欢迎您在Shiny美好而强大的世界中;)

I do not like giving a fully-written answer. 我不喜欢给出完整的答案。 But I recently did something similar. 但是我最近做了类似的事情。 So here are some tips: 因此,这里有一些提示:
* I would recommend you to cut your code into pieces. *我建议您将代码分成几部分。 I recently had some issues with a large Shiny module and cutting it into pieces (and writing abstract modules using (this)[ https://www.r-bloggers.com/the-shiny-module-design-pattern/] ) really helped. 最近,我在使用大型Shiny模块时遇到了一些问题,并将其切成碎片(并使用(this)[ https://www.r-bloggers.com/the-shiny-module-design-pattern/]编写抽象模块)帮助。
* Also, check out for these functions: do.call() , switch() for different cases, formals() to check for a function argument (helpful to write the rest). *此外,请检查以下功能: do.call()switch()用于不同情况, formals()检查功能参数(有助于编写其余部分)。

I might have better written this as a comment (let me know, I am not perfectly used to SO yet), but giving good practices seem to be more important than giving all-made answers. 我可能最好将其写为评论(让我知道,我还不十分习惯),但是提供良好的实践似乎比给出完整的答案更为重要。

Enjoy and let me know if I well understood your issue. 请尽情享受,让我知道我是否完全了解您的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM