web-dev-qa-db-fra.com

brillant 4 petits textesBoîtes d'entrée côte à côte

J'ai un serveur brillant version 0.4.0 et je veux avoir 4 petites boîtes de texte pour ressembler à ceci:

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

Ils ressemblent maintenant à ceci:

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

Avec ce code:

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

Des idées pour y parvenir?

EDITED: J'ai réussi à changer des choses comme ça ailleurs dans le code:

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

Et voici à quoi cela ressemble pour ceux qui ne fonctionnent pas:

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

ÉDITÉ:

Voici un exemple autonome ui.R cela ne fonctionne pas:

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

Page résultante:

enter image description here

61
719016

pour paraphraser (et pour simplifier dans le cas de 2 entrées), votre problème est 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) {}
))

spectacles

enter image description here

Mais vous voulez des petites entrées côte à côte, comme ceci:

small row

La réponse courte

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

donne:

enter image description here

La réponse longue

Entrées côte à côte

Faisons d'abord côte à côte:

Actuellement, textInput génère deux balises distinctes - la label et la input, chacune étant configurée par CSS comme display:block, Ce qui signifie que c'est un rectangle qui se cassera vers la gauche côté du conteneur. Nous devons envelopper le champ de chaque textInput dans un nouveau conteneur (div) et dire à ce conteneur que le conteneur qui le suit (le textInput suivant) est autorisé à être sur la même ligne horizontale sur la page, en utilisant display:inline-block de CSS.

Nous ajoutons donc une div avec un style autour de chaque textInput:

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

Petites entrées

Maintenant, parlons des petits. Il y a plusieurs façons de faire petit,

  1. rendre la police plus petite,
  2. faire en sorte que la zone de saisie contienne moins de caractères.
  3. dites à css ou (ici) bootstrap pour dessiner une boîte plus petite

Puisque bootstrap.js Contrôle vraiment la mise en page lorsque nous utilisons shiny, seuls 3 fonctionneront de manière fiable, alors utilisons-le.

Les tailles d'entrée sont documentées dans documentation Bootstrap 2.3.2 CSS Forms, sous 'Control Sizing' . Il comprend une variété de tailles de mini, petit, moyen, grand, xlarge et xxlarge, et la valeur par défaut est probablement moyenne. Essayons plutôt petit.

Pour définir la taille, nous devons changer la classe de la balise input générée par textInput.

Maintenant, textInput n'est qu'une fonction de commodité autour des fonctions tags plus puissantes telles que tags$label Et tags$input. Nous pouvons construire une version plus puissante de textInput qui nous permet de configurer les éléments, en particulier la classe du nœud 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

Et nous avons terminé - mais nous pouvons regrouper certaines de ces fonctionnalités en demandant à textInput3 De générer la balise div. Cela pourrait également définir la classe par lui-même, mais je vous laisse le soin d'écrire.

Envelopper

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

Par intérêt, voici la version utilisant la classe input-mini:

enter image description here

109
Alex Brown

En utilisant la dernière version de Shiny, vous pouvez accomplir cela en plaçant les appels d'entrée dans un splitLayout (). Cela divisera la ligne fluide, la boîte, etc. en colonnes nécessaires pour afficher vos champs de saisie côte à côte.

L'exemple ci-dessous vous donnera trois entrées de texte dans une boîte, qui apparaîtront côte à côte dans le 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")
      )
  )
)
58
Nadir Sidi

Peut-être que cette solution n'existait pas en 2013, mais si vous voulez le faire sans écrire HTML ou CSS, vous pouvez simplement utiliser la fonction column dans un fluidRow comme ceci:

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

Et cela mettra les choses côte à côte.

EDIT: Il existe maintenant un autre moyen très simple de le faire en utilisant la fonction splitLayout(). Voir la réponse de Nadir Sidi pour plus de détails.

36
C W

J'ai supprimé l'ancienne réponse - en voici une qui fonctionne:

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

  ))
))

Voici les modifications que j'ai apportées:

1) J'ai supprimé les select de select#xlimitsmax Et select#xlimitsmin Dans vos instructions .css

2) J'ai placé vos deux contrôles chacun dans leur propre div() et leur ai donné les noms XXmin et XXmax. J'ai ensuite ajouté des instructions .css Pour les rendre en bloc.

Si vous en avez plusieurs, vous pouvez utiliser une instruction class, telle que:

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

vous pouvez ensuite étiqueter chacun des contrôles div() comme class="MyClass" et utiliser une seule instruction .css.

Modifié pour ajouter: Merci d'avoir publié l'exemple de code - cela a facilité les choses.

2e édition: Juste pour clarifier. Le point de placer les commandes textInput dans une fonction div() est d'unir la zone de saisie et son étiquette en un seul objet afin que les styles (dans ce cas le style display) peut être appliqué. Si vous ne le faites pas, l'étiquette et la boîte agissent comme deux entités distinctes et il est plus difficile de les manipuler dans des cas comme celui-ci.

8
John Paul

Au lieu de mettre des déclarations de style verbeux dans une classe, il semble que vous puissiez facilement étendre les fonctions des balises brillantes à votre goût. Celui-ci serait pratique d'avoir autour par défaut. (c'est avec shiny shiny_0.14.1). Je pensais que j'allais avoir besoin d'écrire une clôture, mais cela semble fonctionner.

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
Nathan Siemers

Si vous voulez les entrées dans mainPanel, vous pouvez utiliser ce qui suit:

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

Ajouter:

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

dans un fichier css (par exemple, style.css dans le répertoire www /) dans votre application et sourcez-le depuis ui.R avec:

includeCSS ('www/style.R')

Je ne sais pas pourquoi vous avez besoin d'un textInput plutôt que d'un numericInput puisque l'entrée que vous semblez rechercher est numérique. Si vous choisissez numericInput, vous pouvez simplement remplacer textInput par numericInput ci-dessus. Si vous voulez les entrées dans le panneau latéral, vous pouvez utiliser le code ci-dessous. Le même fichier css mentionné ci-dessus serait nécessaire.

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

Je n'étais pas satisfait de splitLayout() car il introduit des barres de défilement lorsque l'espace est limité.

J'ai trouvé que, au moins pour les widgets d'entrée comme les boutons ou les zones de texte, une solution assez simple avec un meilleur comportement réactif utilise flex-box: (voir ce grand guide: 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")
  )
)

Il est possible de régler les largeurs relatives. Correspondant à 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")
  )
)
0
sgrubsmyon