【问题标题】:shiny 4 small textInput boxes side-by-side闪亮的 4 个小文本输入框并排
【发布时间】:2014-01-05 09:32:53
【问题描述】:

我有一个闪亮的服务器版本 0.4.0,我希望有 4 个小文本输入框,如下所示:

x-min x-max y-min y-max
[...] [...] [...] [...]

它们现在看起来像这样:

x-min 
[...................]
x-max
[...................]
y-min 
[...................]
y-max 
[...................]

使用此代码:

textInput(inputId="xlimitsmin", label="x-min", value = 0.0),
textInput(inputId="xlimitsmax", label="x-max", value = 0.5),
textInput(inputId="ylimitsmin", label="y-min", value = 0.5),
textInput(inputId="ylimitsmax", label="y-max", value = 1.0),

任何想法如何实现这一目标?

已编辑:我已经成功地在代码的其他地方更改了这样的内容:

<style type="text/css">select#yaxis4 { height: 280px; width: 500px; }</style>
[... which links to this later on in the page...]
          <label class="control-label" for="yaxis4">Y-Axis</label>
          <select id="yaxis4" multiple="multiple">

这就是那些不起作用的样子:

<style type="text/css">select#xlimitsmax { display: inline-block; max-width: 50px; }</style>
[... which links to...]
          <label>x-max</label>
          <input id="xlimitsmax" type="text" value="0.5"/>

已编辑:

这是一个不起作用的独立示例ui.R

library(shiny)
shinyUI(
pageWithSidebar(
  # application title
  headerPanel("test01"),
  sidebarPanel(
    tags$head(
      tags$style(type="text/css", "select { max-width: 360px; }"),
      tags$style(type="text/css", ".span4 { max-width: 360px; }"),
      tags$style(type="text/css",  ".well { max-width: 360px; }")
              ),
    wellPanel(
      p(strong("Side Panel:"))
             )
   ),
  mainPanel(
    textInput(inputId="xlimitsmin", label="x-min", value = 0.0),
    tags$head(tags$style(type="text/css", "select#xlimitsmin { max-width: 50px }")),
    textInput(inputId="xlimitsmax", label="x-max", value = 0.5),
    tags$head(tags$style(type="text/css", "select#xlimitsmax { display: inline-block; max-width: 50px; }"))
    )
))

结果页面:

【问题讨论】:

  • 代码中的&lt;style&gt; 语句在哪里?如果您只是执行更改选择框颜色之类的操作,是否可行?
  • 样式声明分散在闪亮的 ui.R 文件中,并放入 html 头部 (tags$head(tags$style(type="text/css", "select#something { height: 200px; width: 300px; }")))。如果我执行以下操作,仍然无法正常工作:tags$head(tags$style(type="text/css", "select#xlimitsmin { max-width: 50px }"))
  • 平! 6 小时内的赏金 - 你能分配给某人吗?
  • 我还有 16 小时的时间吗?明天我会在 12 小时后在办公室尝试答案。

标签: r shiny


【解决方案1】:

我删除了旧答案 - 这是一个有效的答案:

ui.r:

library(shiny)
shinyUI(
  pageWithSidebar(
  # application title
  headerPanel("test01"),
  sidebarPanel(
     tags$head(
        tags$style(type="text/css", "select { max-width: 360px; }"),
        tags$style(type="text/css", ".span4 { max-width: 360px; }"),
        tags$style(type="text/css",  ".well { max-width: 360px; }")
      ),
     wellPanel(
        p(strong("Side Panel:"))
     )
  ),

 mainPanel(

    div(id="XXmin",textInput(inputId="xlimitsmin", label="x-min", value = 0.0)),
    tags$head(tags$style(type="text/css", "#XXmin {display: inline-block}")),
    tags$head(tags$style(type="text/css", "#xlimitsmin {max-width: 50px}")),

    div(id="XXmax",textInput(inputId="xlimitsmax", label="x-max", value = 0.5)),
    tags$head(tags$style(type="text/css", "#XXmax {display: inline-block}"),
    tags$head(tags$style(type="text/css", "#xlimitsmax {max-width: 50px}"))

  ))
))

以下是我所做的更改:

1) 我在您的 .css 语句中从 select#xlimitsmaxselect#xlimitsmin 中删除了 select

2) 我将您的两个控件分别放在自己的div() 中,并给它们命名为XXminXXmax。然后我添加了.css 语句以使它们成为内联块。

如果你有一堆这样的,你可能想使用class 语句 - 例如:

div(class="MyClass",textInput(inputId="xlimitsmin", label="x-min", value = 0.0)),
tags$head(tags$style(type="text/css", ".MyClass {display: inline-block}")),
tags$head(tags$style(type="text/css", "#xlimitsmin {max-width: 50px}")),

然后您可以将每个控件div() 标记为class="MyClass" 并仅使用一个.css 语句。

已编辑添加:感谢您发布示例代码 - 这使它变得更加容易。

第二次编辑:只是为了澄清。将textInput 命令放在div() 中的目的是将输入框及其标签合并到一个对象中,以便可以应用样式(在本例中为display 样式)。如果您不这样做,标签和框将作为两个独立的实体,在这种情况下更难操作它们。

【讨论】:

    【解决方案2】:

    如果您想在 mainPanel 中输入,您可以使用以下内容:

    div(class="row-fluid",
      div(class="span1",textInput("xlimitsmin", label = "x-min", value = 0.0)), 
      div(class="span1",textInput("xlimitsmax", label = "x-max", value = 0.5)),
      div(class="span1",textInput("ylimitsmin", label = "y-min", value = 0.5)),
      div(class="span1",textInput("ylimitsmax", label = "y-max", value = 1.0))
    )
    

    添加:

    #xlimitsmin, #xlimitsmax, #ylimitsmin, #ylimitsmax { 
        max-width: 25px; 
    }
    

    在您的应用程序中的 css 文件(例如,www/ 目录中的 style.css)中,并使用以下命令从 ui.R 获取它:

    includeCSS('www/style.R')

    我不确定您为什么需要 textInput 而不是 numericInput,因为您似乎正在寻找的输入是数字。如果您选择 numericInput,您可以简单地将 textInput 替换为上面的 numericInput。如果您想要 sidebarPanel 中的输入,您可以使用下面的代码。将需要上述相同的 css 文件。

    div(class="row-fluid",
        div(class="span3",numericInput("xlimitsmin", label = "x-min", value = 0.0)), 
        div(class="span3",numericInput("xlimitsmax", label = "x-max", value = 0.5)),
        div(class="span3",numericInput("ylimitsmin", label = "y-min", value = 0.5)),
        div(class="span3",numericInput("ylimitsmax", label = "y-max", value = 1.0))
    )
    

    【讨论】:

      【解决方案3】:

      解释(并简化为 2 个输入的情况),您的问题是:

      runApp(list(
          ui = bootstrapPage(
              textInput(inputId="xlimitsmin", label="x-min", value = 0.0),
              textInput(inputId="xlimitsmax", label="x-max", value = 0.5)
          ),
          server = function(input, output) {}
      ))
      

      表演

      但是你想要并排的小输入,像这样:

      简短的回答

      textInputRow<-function (inputId, label, value = "") 
      {
          div(style="display:inline-block",
              tags$label(label, `for` = inputId), 
              tags$input(id = inputId, type = "text", value = value,class="input-small"))
      }
      runApp(list(
          ui = bootstrapPage(
              textInputRow(inputId="xlimitsmin", label="x-min", value = 0.0),
              textInputRow(inputId="xlimitsmax", label="x-max", value = 0.5)
          ),
          server = function(input, output) {}
      ))
      

      给予:

      长答案

      并排输入

      让我们先并排:

      目前 textInput 会生成两个单独的标签 - labelinput,每个标签都由 CSS 配置为 display:block,这意味着它是一个矩形,会在容器的左侧断开。我们需要将每个textInput 的字段包装在新容器(div)中,并告诉该容器跟随它的容器(下一个textInput)允许在页面上的同一水平行上,使用CSS 的@ 987654335@.

      所以我们在每个 textInput 周围添加一个带有样式的 div:

      runApp(list(
          ui = bootstrapPage(
              div(style="display:inline-block",textInput(inputId="xlimitsmin", label="x-min", value = 0.0)),
              div(style="display:inline-block",textInput(inputId="xlimitsmax", label="x-max", value = 0.5))
          ),
          server = function(input, output) {}
      ))
      

      小输入

      现在让我们来处理小问题。做小事有几种方法,

      1. 字体变小,
      2. 使输入框中的字符更少。
      3. 告诉 css 或(此处)bootstrap 绘制一个较小的框

      由于bootstrap.js 在我们使用闪亮时确实可以控制布局,所以只有 3 个可以可靠地工作,所以让我们使用它。

      输入大小记录在Bootstrap 2.3.2's CSS Forms documentation, under 'Control Sizing' 中。它包括从 mini、small、medium、large、xlarge 和 xxlarge 的各种尺寸,默认可能是 medium。让我们尝试小一点。

      要设置大小,我们需要更改textInput生成的input标签的类。

      现在textInput 只是更强大的tags 函数(例如tags$labeltags$input)的便捷函数。我们可以构建一个更强大的textInput 版本,它允许我们配置元素,特别是input 节点的类:

      textInput2<-function (inputId, label, value = "",...) 
      {
          tagList(tags$label(label, `for` = inputId), tags$input(id = inputId, 
                                                                 type = "text", value = value,...))
      }
      runApp(list(
          ui = bootstrapPage(
              div(style="display:inline-block",textInput2(inputId="xlimitsmin", label="x-min", value = 0.0, class="input-small")),
              div(style="display:inline-block",textInput2(inputId="xlimitsmax", label="x-max", value = 0.5, class="input-small"))
          ),
          server = function(input, output) {}
      ))
      

      我们已经完成了——但是我们可以通过让textInput3 生成 div 标签来扩展其中的一些功能。它也可以自己设置类,但我会留给你写。

      总结

      textInput3<-function (inputId, label, value = "",...) 
      {
          div(style="display:inline-block",
              tags$label(label, `for` = inputId), 
              tags$input(id = inputId, type = "text", value = value,...))
      }
      runApp(list(
          ui = bootstrapPage(
              textInput3(inputId="xlimitsmin", label="x-min", value = 0.0, class="input-small"),
              textInput3(inputId="xlimitsmax", label="x-max", value = 0.5, class="input-small")
          ),
          server = function(input, output) {}
      ))
      

      出于兴趣,这里是使用 input-mini 类的版本:

      【讨论】:

        【解决方案4】:

        也许这个解决方案在 2013 年还没有出现,但如果你想在不编写 HTML 或 CSS 的情况下做到这一点,你可以像这样在 fluidRow 中使用 column 函数:

          fluidRow(
            column(3,
            selectInput('pcat', 'Primary Category', c("ALL", "Some"))),
            column(3,
            selectInput('smodel', 'Statistical Model', c("NONE", "LINEAR REGRESSION", "LOWESS")))
          )
        

        它会把东西并排放置。

        编辑:现在有另一种非常简单的方法可以使用splitLayout() 函数来执行此操作。有关详细信息,请参阅 Nadir Sidi 的答案。

        【讨论】:

        • 谢谢!这让我头疼不已,幸运的是我向下滚动了答案,这很可能是最好的方法。
        • 我也喜欢这个解决方案。如果你有下拉菜单,splitLayout 会引入滚动条,这使得它对于这种类型的输入非常不足。但是有了专栏,效果很好!
        【解决方案5】:

        作为在类中放置冗长样式声明的替代方法,您似乎可以根据自己的喜好轻松扩展闪亮的标签功能。默认情况下,这个特定的会很方便。 (这是闪亮的 shiny_0.14.1 )。以为我需要编写一个闭包,但这似乎可行。

        inline = function (x) {
        tags$div(style="display:inline-block;", x)
        }
        
        inline(textInput(inputId="xlimitsmin", label="x-min", value = 0.0)),
        inline(textInput(inputId="xlimitsmax", label="x-max", value = 0.5)),
        inline(textInput(inputId="ylimitsmin", label="y-min", value = 0.5)),
        inline(textInput(inputId="ylimitsmax", label="y-max", value = 1.0)),
        

        【讨论】:

        • 我喜欢这个答案,这有助于解决其他问题。谢谢
        • 事实上,这是我摆脱不需要的水平滚动条的唯一方法。谢谢!
        【解决方案6】:

        使用 Shiny (>= 0.11),您可以通过将输入调用放在 splitLayout() 中来完成此操作。这会将流动的行、框等拆分为并排显示输入字段所需的列。

        下面的示例将在一个框中为您提供三个文本输入,它们将并排显示在 fluidRow 中。

        fluidRow(
          box(width = 12, title = "A Box in a Fluid Row I want to Split", 
              splitLayout(
                textInput("inputA", "The first input"),
                textInput("inputB", "The second input"),
                textInput("inputC", "The third input")
              )
          )
        )
        

        【讨论】:

        • +1,splitLayout还允许你自定义每个单元格的宽度; splitLayout(cellWidths = c("25%", "75%"), plotOutput("plot1"), plotOutput("plot2") )
        • 这应该是现在公认的答案,这正是 OP 所追求的。
        • 而函数box来自shinydashboard
        • 这比接受的答案容易得多,谢谢 Nadir。
        • 这会将输入放置在可滚动的列中,因此当您单击下拉菜单时,它不会呈现预期效果,并且输入和下拉元素会上下滚动。
        【解决方案7】:

        我对@9​​87654322@ 不满意,因为它在空间有限时引入了滚动条。

        我发现,至少对于像按钮或文本框这样的输入小部件,使用 flex-box 具有更好的响应行为的非常简单的解决方案:(请参阅此出色指南:https://css-tricks.com/snippets/css/a-guide-to-flexbox/

        div(
          style = "display: flex; flex-wrap: wrap;",
          div(
            style = "flex: 1;",
            textInput("inputA", "The first input")
          ),
          div(
            style = "flex: 1;",
            textInput("inputB", "The second input")
          ),
          div(
            style = "flex: 1;",
            textInput("inputC", "The third input")
          )
        )
        

        可以调整相对宽度。对应splitLayout(cellWidths = c("25%", "75%"), ...)

        div(
          style = "display: flex; flex-wrap: wrap;",
          div(
            style = "flex: 1;",
            textInput("inputA", "The first input")
          ),
          div(
            style = "flex: 3;", # second item 3 times as wide as first one
            textInput("inputB", "The second input")
          )
        )
        

        【讨论】:

          【解决方案8】:

          Sgrubsmyon 的方法对我来说几乎是完美的,但是我遇到了 flex-box 方法的一个新问题,即输入之间没有填充。显然,这与“display: flex”是“flex-grow 1”的包装器有关,它用尽了所有可用空间。我钻进了兔子洞,但无法让它工作,但了解了一种使用“CSS - Grid”的类似方法,并且更容易(relevant SO question where I learnt this from)

          div(
            style = "display: grid; 
                    grid-template-columns: 20% repeat(3, 20%); ## same as repeat(4, 20%)
                    grid-gap: 10px;",
          
              textInput("inputA", "The first input"),
          
              textInput("inputB", "The second input"),
          
              textInput("inputC", "The third input"),
          
              textInput("inputD", "The fourth input")
          
          )
          

          CSS - Grid 方法也有一个类似的很棒的指南,位于here,您可以在其中了解所有不同的参数和您可以使用的可定制性。请注意,我在写这个答案之前的 2 小时之前从未接触过 CSS,所以欢迎任何更正 =)

          【讨论】:

            猜你喜欢
            • 2018-11-14
            • 2016-03-23
            • 1970-01-01
            • 1970-01-01
            • 2021-01-14
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多