如何在 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 中输入的值,确保它们属于预定义列表?的主要内容,如果未能解决你的问题,请参考以下文章
R Shiny 不会在闪亮的应用程序中显示输出,而只会在控制台中显示输出(以及如何正确计算子组的平均值)?
Shiny:在控制台中显示服务器和 ui 之间的消息的选项设置是啥