如何在 Shiny 中控制 selectizeInput 中输入的值,确保它们属于预定义列表?

Posted

技术标签:

【中文标题】如何在 Shiny 中控制 selectizeInput 中输入的值,确保它们属于预定义列表?【英文标题】:how to control the values entered in selectizeInput in Shiny, making sure they belong to a predifined list? 【发布时间】:2020-12-16 06:34:50 【问题描述】:

我希望当用户退出 selectizeInput 字段(在 selectizeInput 之外单击)时,会创建并选择一个新选项(选项 createOnBlur = TRUE),但我不知道如何控制创建的值以确保它们属于“选择”列表。

事实上,我希望 createOnBlur=TRUE 与 create=FALSE 一起使用,但这显然行不通..

我查看了 selectize.js 文档,我认为 createFilter 和/或 onBlur() 选项可能很有用,但我没有成功实现它。

这是一个带有年龄输入的reprex,当用户录制例如“40”然后在输入之外点击而不按“Enter”(即onBlur),值40被记录在输入中,但如果用户磁带例如“444”,这个不可能的年龄值不会在选择列表中创建:

library(shiny)

input_age <- function(mina = 0, maxa =100)
  
  selectizeInput(inputId = "age", 
                 label = "Age",
                 choices = c("choose one" = "", mina:maxa),
                 options = list(create = TRUE,
                                createOnBlur = TRUE)
                 
  ) 
  


ui <- shinyUI(fluidPage(
  
  titlePanel("selectize createonblur"),
  
  mainPanel(
    input_age(mina = 20, maxa = 70)
  ) 

))

# SERVER
server <- shinyServer(function(input, output) 
)

shinyApp(ui, server)

【问题讨论】:

【参考方案1】:

在每次与您的输入交互后,您可以使用updateSelectizeInput 来检查所做的选择是否与选择相匹配。

请看以下内容:

library(shiny)

input_age <- function(mina = 0, maxa = 100)
  
  selectizeInput(inputId = "age", 
                 label = "Age",
                 choices = c("choose one" = "", mina:maxa),
                 options = list(create = TRUE,
                                createOnBlur = TRUE)
                 
  ) 
  


minAge <- 20
maxAge <- 70

ui <- shinyUI(fluidPage(
  
  titlePanel("selectize createonblur"),
  
  mainPanel(
    input_age(mina = minAge, maxa = maxAge)
  ) 
  
))

# SERVER
server <- shinyServer(function(input, output, session) 
  observeEvent(req(input$age), 
    if(length(setdiff(input$age, as.character(seq(minAge, maxAge)))) > 0)
      updateSelectizeInput(session,
                           inputId = "age",
                           choices = seq(minAge, maxAge),
                           selected = "")  
    
  )
  
)

shinyApp(ui, server)

更新 - 这是一个 JS 方法:

library(shiny)

input_age <- function(mina = 0, maxa = 100)
  selectizeInput(inputId = "age", 
                 label = "Age",
                 choices = c("choose one" = "", mina:maxa),
                 options = list(create = TRUE,
                                createOnBlur = TRUE))


ui <- shinyUI(fluidPage(
  tags$head(tags$script(html("
                  $(document).on('shiny:inputchanged', function(event) 
                    if (event.name === 'age') 
                        if (isNaN(parseInt(event.value)) || event.value > 70 || event.value < 20) 
                        var $select = $('#age').selectize();
                        var selectize = $select[0].selectize;
                        selectize.setValue(null, true);
                        
                    
                  );
            "))),
  titlePanel("selectize createonblur"),
  mainPanel(
    input_age(mina = 20, maxa = 70)
  ) 
  
))

# SERVER
server <- shinyServer(function(input, output, session) 
)

shinyApp(ui, server)

【讨论】:

感谢您在服务器端提供此解决方案!您是否知道是否有办法在 ui 端实现相同的解决方案,例如使用“onblur()”或 createfilter 选项?【参考方案2】:

您可以为createFilter 选项提供正则表达式。如果用户键入的内容与此正则表达式不匹配,则“添加...”将不会出现,并且无法添加此项目。

library(shiny)

ui <- fluidPage(
  titlePanel("selectize createonblur"),
  mainPanel(
    selectizeInput(
      inputId = "age", 
      label = "Age",
      choices = c("choose one" = "", 20:70),
      options = list(
        create = TRUE,
        createOnBlur = TRUE,
        createFilter = I("/^([2-6][0-9]|70)$/")
      )
    ) 
  ) 
)

server <- function(input, output, session) 

shinyApp(ui, server)

【讨论】:

嗨@StéphaneLaurent 刚刚尝试使用上述代码 - 我仍然可以添加“444”作为选择。 是的,我认为这是因为字符串 '44' 包含在 '444' 中。实际上,您不能添加“112”,但可以添加“120”,因为与“20”匹配...更糟糕的行为:您可以添加“44anything”! 但无论如何,非常感谢你们两位的回答! @Youenn 抱歉,合适的正则表达式是I("/^([2-6][0-9]|70)$/")。我编辑。 完美谢谢!我真的需要提高我的正则表达式技能。

以上是关于如何在 Shiny 中控制 selectizeInput 中输入的值,确保它们属于预定义列表?的主要内容,如果未能解决你的问题,请参考以下文章

在 Shiny 的 DataTable 实现中控制数字格式

R Shiny 不会在闪亮的应用程序中显示输出,而只会在控制台中显示输出(以及如何正确计算子组的平均值)?

Shiny:在控制台中显示服务器和 ui 之间的消息的选项设置是啥

使用Shiny滑块控制ggplot上的输出

更新 bs4dash 版本 2.00 Shiny 中的控制栏

如何在 RMarkdown 中使用 Shiny 进行嵌套选择 selectInput()?