Shiny DT表格中Selectize处理后selectInput垂直居中问题求助
Shiny DT表格中Selectize多选组件的两个问题
我在Shiny的DT数据表格里嵌入了selectInput组件,开启multiple = TRUE时格式异常,必须用自定义JavaScript对其做Selectize处理才能正常显示多选功能。但遇到两个问题:
- 必须添加隐藏的“dummy”
selectInput才能让Selectize生效,不清楚原因; - Selectize处理后,组件无法在表格行内垂直居中:如果注释掉
initComplete代码,组件能靠margin-bottom: 0的CSS设置垂直居中,但会丢失正确格式和多选功能。希望在保留功能和格式的前提下实现垂直居中。
简化代码
require(shiny) require(DT) # 对指定ID的输入应用Selectize SelectizeIDs <- function(ids) { myStrings <- as.character(sapply(ids, function(id) { paste0(" $('#", id, "').selectize();") })) c( "function(settings){", myStrings, "}" ) } shinyApp( ui = fluidPage( tags$head(tags$style(HTML("td .form-group {margin-bottom: 0;}"))), # 必须加这个隐藏的dummy组件,否则Selectize不生效 div(style = "display: none;", selectInput(inputId = "dummy", label = NULL, choices = 1:2)), DT::dataTableOutput("mytable") ), server = function(input, output, session) { output$mytable <- DT::renderDataTable({ DT::datatable( data = data.frame( Col1 = as.character(selectInput( inputId = "id1", label = NULL, choices = letters, multiple = TRUE )) ), escape = FALSE, selection = "none", options = list( initComplete = JS(SelectizeIDs("id1")) ) ) }) } )
效果对比
Selectize生效但未垂直居中:

垂直居中但格式/功能异常:

解决方案
1. 为什么需要dummy selectInput?
Shiny默认只会在页面初始加载时,根据存在的原生组件自动引入对应依赖资源(Selectize的CSS/JS)。表格中的selectInput是通过DT动态渲染生成的,页面加载时不存在该组件,Shiny不会主动加载Selectize依赖,导致后续调用selectize()方法时找不到对应函数。添加隐藏的dummy组件,就是为了触发Shiny自动加载Selectize的依赖资源。
2. 实现Selectize组件垂直居中
Selectize初始化后会替换原生select元素,生成的新DOM结构自带默认margin和padding,破坏了原有垂直居中布局。需要添加针对性CSS调整:
修改tags$style部分,并优化Selectize初始化时的宽度设置:
require(shiny) require(DT) SelectizeIDs <- function(ids) { myStrings <- as.character(sapply(ids, function(id) { paste0(" $('#", id, "').selectize({width: '100%'});") })) c( "function(settings){", myStrings, "}" ) } shinyApp( ui = fluidPage( tags$head(tags$style(HTML(" td .form-group {margin-bottom: 0;} /* 让Selectize容器占满表格行高度并垂直居中 */ td .selectize-control { margin: 0; display: flex; align-items: center; height: 100%; } /* 调整输入框内边距,适配表格行高 */ td .selectize-input { padding: 4px 8px; min-height: auto; } "))), div(style = "display: none;", selectInput(inputId = "dummy", label = NULL, choices = 1:2)), DT::dataTableOutput("mytable") ), server = function(input, output, session) { output$mytable <- DT::renderDataTable({ DT::datatable( data = data.frame( Col1 = as.character(selectInput( inputId = "id1", label = NULL, choices = letters, multiple = TRUE )) ), escape = FALSE, selection = "none", options = list( initComplete = JS(SelectizeIDs("id1")) ) ) }) } )
内容的提问来源于stack exchange,提问作者Ben Ernest
相关产品推荐
相关产品推荐

