shiny 4 texto pequeñoCajas de entrada una al lado de la otra

Tengo una versión de servidor shiny 0.4.0 y quiero tener 4 cuadros de entrada de texto pequeños para que se vean así:

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

Ahora se ven así:

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

Con este código:

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

¿Alguna idea de cómo lograr esto?

EDITADO: He cambiado cosas como esta en otro lugar del código:

 select#yaxis4 { height: 280px; width: 500px; } [... which links to this later on in the page...]   

Y esto es lo que parece para los que no funcionan:

 select#xlimitsmax { display: inline-block; max-width: 50px; } [... which links to...]   

EDITADO:

Aquí hay un ejemplo ui.R que no funciona:

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

Página resultante:

enter image description here

parafraseando (y para simplificar al caso de 2 entradas), su problema es que:

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

muestra

enter image description here

Pero quieres pequeñas entradas una al lado de la otra, así:

pequeña fila

La respuesta corta

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

da:

enter image description here

La respuesta larga

Entradas lado a lado

Hagamos primero uno al lado del otro:

Actualmente, TextInput genera dos tags separadas: la label y la input , cada una de las cuales es configurada por CSS como display:block , lo que significa que es un rectángulo que se romperá en el lado izquierdo del contenedor. Necesitamos envolver el campo de cada entrada de texto en un contenedor nuevo (div) y decirle a ese contenedor que el contenedor que lo sigue (la siguiente entrada de texto) puede estar en la misma fila horizontal en la página, usando la display:inline-block de CSS display:inline-block .

Así que agregamos un div con un estilo alrededor de cada entrada de texto:

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

fila

Pequeñas entradas

Ahora vamos a tratar con pequeño. Hay algunas formas de hacer cosas pequeñas,

  1. hacer la fuente más pequeña,
  2. hacer que el cuadro de entrada tenga menos caracteres.
  3. dile css o (aquí) bootstrap para dibujar un cuadro más pequeño

Ya que bootstrap.js controla realmente el diseño cuando usamos shiny, solo 3 funcionarán de manera confiable, así que usemos eso.

Los tamaños de entrada están documentados en la documentación de Formularios CSS de Bootstrap 2.3.2, en 'Tamaño de control' . Incluye una variedad de tamaños desde mini, pequeño, mediano, grande, xlarge y xxlarge, y el valor predeterminado es probablemente medio. Probemos pequeño, en cambio.

Para establecer el tamaño, necesitamos cambiar la clase de la etiqueta de input generada por la input de texto.

Ahora, textInput es solo una función de conveniencia alrededor de las funciones de tags más potentes, como las tags$label y tags$input . Podemos construir una versión más poderosa de textInput que nos permita configurar los elementos, específicamente la clase del nodo de 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) {} )) 

pequeña fila

Y hemos terminado, pero podemos mejorar parte de esta funcionalidad haciendo que textInput3 genere la etiqueta div. También podría establecer la clase por sí mismo, pero lo dejo para que usted escriba.

Envolviendolo

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

Por interés, esta es la versión que usa la clase input-mini :

enter image description here

Utilizando la última versión de Shiny, puede lograr esto colocando las llamadas de entrada dentro de un splitLayout (). Esto dividirá la fila de fluido, la caja, etc. en las columnas necesarias para mostrar sus campos de entrada uno al lado del otro.

El siguiente ejemplo le daría tres entradas de texto en un cuadro, que aparecerán lado a lado en el fluidoRow.

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

Tal vez esta solución no existía en 2013, pero si quieres hacer esto sin escribir HTML o CSS, puedes usar la función de column dentro de un fluidRow así:

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

Y colocará las cosas una al lado de la otra.

EDITAR: Ahora hay otra manera muy fácil de hacerlo utilizando la función splitLayout() . Vea la respuesta de Nadir Sidi para más detalles.

Eliminé la respuesta anterior; aquí hay una que funciona:

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

Aquí están los cambios que hice:

1) select#xlimitsmax la select de select#xlimitsmax y select#xlimitsmin en sus declaraciones select#xlimitsmin

2) Puse tus dos controles cada uno en su propio div() y les di los nombres XXmin y XXmax . Luego agregué declaraciones .css para convertirlas en bloque en línea.

Si tiene muchos de estos, es posible que desee usar una statement de class , como por ejemplo:

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

luego puede etiquetar cada uno de los controles div() como class="MyClass" y usar solo una statement .css .

Editado para agregar: gracias por publicar el código de ejemplo, eso lo hizo mucho más fácil.

2da edición: solo para aclarar. El objective de colocar los comandos textInput dentro de un div() es unir el cuadro de entrada y su etiqueta en un solo objeto para que se puedan aplicar los estilos (en este caso, el estilo de display ). Si no hace esto, la etiqueta y el cuadro actúan como dos entidades separadas y es más difícil manipularlos en casos como este.

Como alternativa a poner declaraciones de estilo detallado en una clase, parece que puede ampliar fácilmente las funciones de tags shinys a su gusto. Este en particular sería conveniente tener alrededor por defecto. (Esto es con shiny shiny_0.14.1). Pensé que iba a necesitar escribir un cierre, pero parece que funciona.

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

Si quiere las entradas en mainPanel, puede usar lo siguiente:

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

Añadir:

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

en un archivo css (p. ej., style.css en el directorio www /) en su aplicación y proceda desde ui.R con:

includeCSS (‘www / style.R’)

No estoy seguro de por qué necesita una entrada de texto en lugar de una entrada numérica ya que la entrada que parece estar buscando es numérica. Si eliges numericInput, puedes simplemente reemplazar textInput con numericInput en el punto anterior. Si quiere las entradas en el panel de la barra lateral, puede usar el siguiente código. El mismo archivo css mencionado anteriormente sería necesario.

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