如果chooserInput的右侧为空,则使用shinyBS禁用actionButton时出现R Shiny错误

时间:2015-05-21 17:12:29

标签: r button shiny

这是我关于stackoverflow的第一个问题,我已经使用R 3个月了。我有很多要学习的!任何帮助深表感谢。提前感谢您的时间。

我想要发生什么: 用户从下拉框中选择一个类别(动物或食物),然后单击下一次。适当的ui组件将呈现和显示。然后,只要Chooser Input组件的右侧框为空,就应禁用(灰显)Next按钮。只有当用户在右侧框中至少有一个选项时,才应启用“下一步”按钮,用户可以单击它。

问题:渲染选配器输入组件后,右侧框为空,但未禁用“下一步”。这是错误:

Warning in run(timeoutMs) :
Unhandled error in observer: argument is of length zero
observeEvent(input$widget2)

下面是一个演示ui.R和sever.R来重现我的问题。 (但是,我将把解决方案实现为更大,更复杂的GUI。)代码使用 shinyBS ,因此您首先需要安装包并加载库。该代码还使用 chooserInput ,它需要两个文件: chooser.R www / chooser-binding.js 。有关更多信息,请参阅以下链接: http://shiny.rstudio.com/gallery/custom-input-control.html

UI

### The following libraries need to be loaded BEFORE runApp()
### library(shiny)
### library(shinyBS)

source("chooser.R") # Used for Custom Input Control UI component (chooserInput)
# chooser.R is saved in the same location as the ui.R and server.R files
# chooserInput also requires chooser-binding JScript script file, which should be located within "www" folder


shinyUI(navbarPage("navbarPage Title",
       tabPanel("tabPanel Title", titlePanel("titlePanel Title"),
            fluidPage(

              #### NEW ROW #####################################################################################################  
              fluidRow(wellPanel(

                #  Instructions for initial screen
                conditionalPanel(condition = "input.ButtonNext == 0", tags$b("Step 1: Choose category and click 'Next'")),

                # Instructions for 'Foods'
                conditionalPanel(condition = "input.ButtonNext == 1 && input.widget1 == 'Foods'", tags$b("Step 2: Move Food(s) of interest to the right box and click 'Next'")),

                # Instructions for 'Animals'
                conditionalPanel(condition = "input.ButtonNext == 1 && input.widget1 == 'Animals'", tags$b("Step 2: Move Animals(s) of interest to the right box and click 'Next'"))

              )),

              #### NEW ROW #####################################################################################################  
              fluidRow( 

                # Drop down box for first selection
                conditionalPanel(
                  condition = "input.ButtonNext == 0", 
                  selectInput("widget1", label = "",
                                choices = c("Foods", 
                                "Animals"))),

                # This outputs the dynamic UI components based on first selection
                uiOutput("ui1")

              ), 

              #### NEW ROW #####################################################################################################  
              fluidRow(tags$hr()), # Horizontal line separating input UI from "Next" button

              #### NEW ROW #####################################################################################################  
              fluidRow(
                column(1, offset=10,
                   # UI component for 'Next' button
                   conditionalPanel(condition = "input.ButtonNext < 2", bsButton("ButtonNext", "Next"))
                ),

                column(1,
                   HTML("<a class='btn' href='/'>Restart</a>")
                )  
              )   


            ) # End of fluidPage 
       ) # End of tabPanel

)) # End of navbarPage and ShinyUI

服务器

shinyServer(function(input, output, session) {


      # Widget to display when number of clicks of "Next" button (ButtonNext) =  1    
      output$ui1 <- renderUI({
        if(input$ButtonNext[1]==1) {

          print("I am in renderUI") # Used to help debug

          # Depending on the initial selection, generate a different UI component
          switch(input$widget1,
                 "Foods" = chooserInput("widget2", "Available frobs", "Selected frobs", leftChoices=c("Apple", "Cheese", "Carrot"), rightChoices=c(), size = 5, multiple = TRUE),
                 "Animals" = chooserInput("widget2", "Available frobs", "Selected frobs", leftChoices=c("Lion", "Tiger", "Bear", "Wolverine"), rightChoices=c(), size = 5, multiple = TRUE)
          )

        } 
      }) # End of renderUI


      # Disable "Next" button when right side of multi select input is empty
      observeEvent(input$widget2, ({

        widget2_right <- input$widget2[[2]]
        print(widget2_right) # Used to help debug

        if(widget2_right == character(0)) {
          updateButton(session, "ButtonNext", disabled = TRUE)
        } else {
          updateButton(session, "ButtonNext", disabled = FALSE)
        }

      })) # End of observeEvent


}) # End of shinyServer

使用优先级和恢复/暂停提到的类似问题(下面的链接)但没有提供示例。如果这是我的问题的有效解决方案,请提供一些代码。

R shiny Observe running Before loading of UI and this causes Null parameters

EXTRA注意:提供的代码是一个小型演示,是从我为用户开发的更大的GUI中重新创建的,可以进行一系列选择,在每个选项之间单击“下一步”。根据他们在每个步骤中所做的选择,将从csv文件生成新选项。因此,呈现和显示的ui组件取决于用户点击“下一步”的次数以及他们之前做出的选择。最后,选择用于对大型数据集进行排序,以便用户只能绘制他们感兴趣的数据。双重条件是我使用conditionalPanel和actionButton的VALUE来呈现和显示当前ui组件的原因。用户需要。我的代码有效(除了上面的问题 - HA!)。但是,我已经读过使用actionButton的VALUE是不好的编码习惯。如果对另一种处理双重条件的方法有任何建议,请告诉我。

1 个答案:

答案 0 :(得分:2)

在server.R中,我替换了

if(widget2_right == character(0))

if(length(widget2_right)==0)

现在该程序按照我的意愿运行。

当右框为空时,widget2_right = character(0)。我了解到,将向量与character(0)进行比较会产生logical(0),而不是TRUEFALSE。但是,length(character(0)) = 0。因此,只要右侧框中没有选择,if(length(widget2_right)==0)将为TRUE