在shiny中如何对齐不等长的checkbox?我想了个笨方法,在每个checkbox的string末尾加入若干个连续的空格(),但是在渲染的时候这些连续的空格都消失了。 示例代码如下

library(shiny)

# Generate sample data
tab_name = sapply(1:20, function(i) paste(rep(LETTERS[i], i), collapse = ""))

# Pad strings with extra blanks at the end to make them the same length
tab_name <- stringr::str_pad(tab_name, width = max(nchar(tab_name)), side = "right", pad = " ")

# ui
ui <- fluidPage(
  # adjust the margin so they can align properly
  tags$head(tags$style(".checkbox-inline {margin: 0 !important;}")),
  
  checkboxGroupInput("tab", "Table Name",
                     choices = tab_name,
                     inline = TRUE)
)

server <- function(input, output){}

shinyApp(ui, server)

示例中只有第一列是对齐的,但由于每个checkbox的长度都不同,其他所有列的checkbox都不能对齐。
我想请问 如何保留checkbox末尾的空格,或者更进一步,如何在不加空格的基础上直接对齐不等长的checkbox。

如果哪里没说清楚我可以再补充信息,谢谢。

    乱试出来一个办法,改用 choiceNames 和 choiceValues 分开给 UI 展示和实际的值,然后在 choiceNames 里面通过 div width 给定宽度

    library(shiny)
    
    # Generate sample data
    tab_name = sapply(1:20, function(i) paste(rep(LETTERS[i], i), collapse = ""))
    
    # Pad strings with extra blanks at the end to make them the same length
    tab_name <- stringr::str_pad(tab_name, width = max(nchar(tab_name)), side = "right", pad = " ")
    
    # ui
    ui <- fluidPage(
      # adjust the margin so they can align properly
      tags$head(tags$style(".checkbox-inline {margin: 0 !important;}")),
      
      checkboxGroupInput("tab", "Table Name",
                         choiceNames = lapply(1:20, function(i) div(style = 'width:400px', tab_name[i])),
                         choiceValues = tab_name,
                         inline = TRUE)
    )
    
    server <- function(input, output){}
    
    shinyApp(ui, server)

    从 UX 角度,可勾选的选项过多时不宜一股脑直接展示…… 可以集中放到一个 dropdown button 类组件下,每行列一个 checkbox,比如 shinyWidgets::virtualSelectInput() 实现的效果。

    sleepstan 不管在什么软件中,只要你想到用一坨空格来对齐什么元素,那基本上一出发就一定走歪了。空格通常不是用来对齐的。对 HTML 来说,连续空格甚至通常是无意义的。

    在本案中,要把这些复选框对齐,那必须让它们的宽度相同才行。你既然已经定义了

    .checkbox-inline {margin: 0 !important;}

    何不继续定义一下它们的宽度呢,比如:

    .checkbox-inline {margin: 0 !important; width: 15em;}

    这里有点麻烦的是选取一个合适的宽度,15em 只是个例子。不同系统不同浏览器可能会渲染出来的网页元素略有差异(主要取决于字体)。理论上,你想要的是所有复选框都设定到最宽的那个复选框的宽度,但这个宽度不太容易动态获取(可以用 JS,但这种办法想想就不够优雅)。而写死一个固定宽度又难以保证它真的是大于等于实际最大宽度。可以保守地设置大一点(比如 20em),而那样问题就是可能会多出太多没用到的空白空间,导致页面骨质疏松。嗯,这就是排版工人的命运,每当你想按下这个葫芦,那头总是会浮起个瓢。整天在细枝末节中纠结权衡取舍。

    示例:

    library(shiny)
    
    # Generate sample data
    tab_name = strrep(LETTERS[1:20], 1:20)
    
    # ui
    ui <- fluidPage(
        # adjust the margin so they can align properly
        tags$head(tags$style(".checkbox-inline {margin: 0 !important; width: 15em;}")),
        
        checkboxGroupInput("tab", "Table Name",
                           choices = tab_name,
                           inline = TRUE)
    )
    
    server <- function(input, output){}
    
    shinyApp(ui, server)

    我个人不推荐直接定义 .checkbox-inline,因为这样会影响页面上其它区域的复选框(如果有的话)。CSS 最好用类似命名空间的方式去管理,免得误伤同类。比如把复选框们放在一个类名为 checkbox-aligned 的层里,然后只对层内的复选框修改样式:

    ui <- fluidPage(
      tags$head(
        tags$style(
          ".checkbox-aligned .checkbox-inline {margin: 0 !important; width: 15em;}"
        )
      ),
      
      div(
        class = "checkbox-aligned",
        checkboxGroupInput("tab", "Table Name", choices = tab_name, inline = TRUE)
      )
    )

    另外,这个太可怕了:

    sapply(1:20, function(i) paste(rep(LETTERS[i], i), collapse = ""))

    以后记得召唤 strrep()。当然,我自己三年前也是用那种啰嗦得可怕的写法而不知 strrep()

    strrep(LETTERS[1:20], 1:20)

    感谢楼上各位的回复,我尝试了下,都能解决我想问的问题。我确实一上来就想歪了。

    我也十分同意选项过多时一起展示不美观,我这就去学习一下shinyWidgets::virtualSelectInput()

    P.S. 感谢指路strrep,又学了一招。

    顺便再问一句要怎么添加“已解决”标签。

      使用shinyWidgets::virtualSelectInput()确实清爽多了。

      library(shiny)
      library(shinyWidgets)
      
      # Generate sample data
      tab_name = strrep(LETTERS[1:20], 1:20)
      
      # ui
      ui <- fluidPage(
      
        virtualSelectInput(
          inputId = "tab",
          label = "Table Name",
          choices = list(
            "Group1" = tab_name[1:10],
            "Group2" = tab_name[11:20]
          ),
          showValueAsTags = TRUE,
          search = TRUE,
          multiple = TRUE
        )
      )
      
      server <- function(input, output){}
      
      shinyApp(ui, server)