如果 chooserInput 的右侧为空,则使用 shinyBS 禁用 actionButton 时出现 R Shiny 错误
R Shiny error when using shinyBS to disable actionButton if right-side of chooserInput is empty
这是我关于 Whosebug 的第一个问题,我已经使用 R 3 个月了。我有很多要学习的!任何帮助深表感谢。预先感谢您的宝贵时间。
我想要发生的事情:
用户从下拉框中选择一个类别(动物或食物)并单击下一步。适当的 ui 组件将呈现并显示。然后,只要 Chooser Input 组件的右侧框为空,Next 按钮就应该被禁用(变灰)。只有当用户在右侧框中至少有一个选择时,才应启用“下一步”按钮,用户才可以单击它。
问题: 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,它需要 uires 两个文件:chooser.R 和 www/chooser-binding.js.有关详细信息,请参阅以下 link:
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
A similar question (link below) mentioned using Priorities and Resume/Suspend 但没有提供示例。如果这是解决我的问题的有效方法,请提供一些代码。
R shiny Observe running Before loading of UI and this causes Null parameters
额外注意:所提供的代码是从我为用户开发的更大的 GUI 重新创建的一个小演示,以便用户进行一系列选择,单击 'Next'在每个选择之间。根据他们在每一步所做的选择,新的选择会从一个 csv 文件中生成。因此,呈现和显示的 ui 组件取决于用户单击 'Next' 的次数以及他们之前所做的选择。最后,选择用于对大型数据集进行排序,以便用户可以仅绘制他们感兴趣的数据。双重条件是我使用 conditionalPanel 和 actionButton 的 VALUE 来呈现和显示当前 ui 用户需要的组件。我的代码有效(除了上面的问题 - 哈!)。但是,我读到使用 actionButton 的 VALUE 是糟糕的编码习惯。如果对处理双重条件的另一种方法有任何建议,请告诉我。
在server.R中,我替换了
if(widget2_right == character(0))
和
if(length(widget2_right)==0)
现在程序可以正常运行了。
当右框为空时,widget2_right = character(0)
。我了解到将向量与 character(0)
进行比较会得到 logical(0)
,而不是 TRUE
或 FALSE
。然而,length(character(0)) = 0
。因此,当右侧框中没有任何选择时,if(length(widget2_right)==0)
将是 TRUE
。
这是我关于 Whosebug 的第一个问题,我已经使用 R 3 个月了。我有很多要学习的!任何帮助深表感谢。预先感谢您的宝贵时间。
我想要发生的事情: 用户从下拉框中选择一个类别(动物或食物)并单击下一步。适当的 ui 组件将呈现并显示。然后,只要 Chooser Input 组件的右侧框为空,Next 按钮就应该被禁用(变灰)。只有当用户在右侧框中至少有一个选择时,才应启用“下一步”按钮,用户才可以单击它。
问题: 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,它需要 uires 两个文件:chooser.R 和 www/chooser-binding.js.有关详细信息,请参阅以下 link: 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
A similar question (link below) mentioned using Priorities and Resume/Suspend 但没有提供示例。如果这是解决我的问题的有效方法,请提供一些代码。
R shiny Observe running Before loading of UI and this causes Null parameters
额外注意:所提供的代码是从我为用户开发的更大的 GUI 重新创建的一个小演示,以便用户进行一系列选择,单击 'Next'在每个选择之间。根据他们在每一步所做的选择,新的选择会从一个 csv 文件中生成。因此,呈现和显示的 ui 组件取决于用户单击 'Next' 的次数以及他们之前所做的选择。最后,选择用于对大型数据集进行排序,以便用户可以仅绘制他们感兴趣的数据。双重条件是我使用 conditionalPanel 和 actionButton 的 VALUE 来呈现和显示当前 ui 用户需要的组件。我的代码有效(除了上面的问题 - 哈!)。但是,我读到使用 actionButton 的 VALUE 是糟糕的编码习惯。如果对处理双重条件的另一种方法有任何建议,请告诉我。
在server.R中,我替换了
if(widget2_right == character(0))
和
if(length(widget2_right)==0)
现在程序可以正常运行了。
当右框为空时,widget2_right = character(0)
。我了解到将向量与 character(0)
进行比较会得到 logical(0)
,而不是 TRUE
或 FALSE
。然而,length(character(0)) = 0
。因此,当右侧框中没有任何选择时,if(length(widget2_right)==0)
将是 TRUE
。