闪亮的4个小文本输入框并排

时间:2013-12-17 14:49:37

标签: r shiny

我有一个闪亮的服务器版本0.4.0,我希望有4个小的textInput框看起来像这样:

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; }"))
    )
))

结果页面:

enter image description here

8 个答案:

答案 0 :(得分:105)

解释(并简化为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) {}
))

显示

enter image description here

但是你想要并排的小输入,如下:

small row

简答

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) {}
))

给出:

enter image description here

答案很长

并排输入

让我们先并肩做:

目前textInput会生成两个单独的标记 - labelinput,每个标记都由CSS配置为display:block,这意味着它是一个向左突破的矩形容器的一面。我们需要将每个textInput的字段包装在新容器(div)中,并告诉该容器允许其后面的容器(下一个textInput)位于页面上的同一水平行上,使用CSS的display:inline-block

因此,我们在每个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) {}
))

row

小输入

现在让我们处理小事。有几种方法可以做小事,

  1. 使字体变小,
  2. 使输入框中包含较少的字符。
  3. 告诉css或(这里)bootstrap画一个小盒子
  4. 由于bootstrap.js在我们使用闪亮时确实可以控制布局,因此只有3个可靠地工作,所以让我们使用它。

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

    要设置尺寸,我们需要更改input生成的textInput标记的类。

    现在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) {}
    ))
    

    small row

    我们已经完成了 - 但是我们可以通过让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的版本:

    enter image description here

答案 1 :(得分:52)

使用最新版本的Shiny,您可以通过将输入调用放在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")
      )
  )
)

答案 2 :(得分:35)

也许这个解决方案在2013年还没有,但是如果你想在不编写HTML或CSS的情况下这样做,你可以在column中使用fluidRow函数,如下所示:
< / p>

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

它将把事情并排放置。

编辑:现在有另一种使用splitLayout()功能的非常简单的方法。有关详细信息,请参阅Nadir Sidi的答案。

答案 3 :(得分:8)

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

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)我在select陈述中删除了select#xlimitsmaxselect#xlimitsmin中的.css

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样式)。如果你不这样做,标签和盒子就像两个独立的实体一样,在这种情况下很难操纵它们。

答案 4 :(得分:6)

作为在类中放置详细样式声明的替代方法,您似乎可以根据自己的喜好轻松扩展闪亮标记函数。默认情况下,这个特别的方便。 (这是闪亮的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)),

答案 5 :(得分: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))
)

答案 6 :(得分:0)

我对splitLayout()不满意,因为当空间有限时,它会引入滚动条。

我发现,至少对于按钮或文本框之类的输入小部件而言,一种具有较好响应行为的相当简单的解决方案是使用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")
  )
)

答案 7 :(得分:0)

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")

)

位于here的CSS-Grid方法也有类似的出色指南,您可以在其中了解可以使用的所有不同参数和可定制性。请注意,直到编写此答案之前2个小时我才接触过CSS,因此欢迎进行任何更正=)