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:
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
Mais vous voulez des petites entrées côte à côte, comme ceci:
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:
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) {}
))
Maintenant, parlons des petits. Il y a plusieurs façons de faire petit,
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) {}
))
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.
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
:
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")
)
)
)
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.
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.
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)),
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))
)
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")
)
)