Ich habe eine glänzende Serverversion 0.4.0 und möchte 4 kleine textInput-Felder haben, die so aussehen:
x-min x-max y-min y-max
[...] [...] [...] [...]
Sie sehen jetzt so aus:
x-min
[...................]
x-max
[...................]
y-min
[...................]
y-max
[...................]
Mit diesem 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),
Irgendwelche Ideen, wie dies erreicht werden kann?
EDITIERT: Ich habe solche Dinge an anderer Stelle im Code erfolgreich geändert:
<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">
Und so sieht es für diejenigen aus, die nicht funktionieren:
<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"/>
EDITIERT:
Hier ist ein eigenständiges Beispiel ui.R
, das nicht funktioniert:
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; }"))
)
))
Resultierende Seite:
<style>
Aussagen? Wenn Sie nur so etwas wie die Farbe des Auswahlfelds ändern, funktioniert das?tags$head(tags$style(type="text/css", "select#something { height: 200px; width: 300px; }"))
) eingefügt . Wenn ich so etwas mache, funktioniert es immer noch nicht:tags$head(tags$style(type="text/css", "select#xlimitsmin { max-width: 50px }"))
Antworten:
Um es zu paraphrasieren (und auf den Fall von 2 Eingaben zu vereinfachen), ist Ihr Problem, dass:
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) {} ))
zeigt an
Aber Sie möchten nebeneinander kleine Eingaben, wie folgt:
Die kurze Antwort
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) {} ))
gibt:
Die lange Antwort
Side-by-Side-Eingänge
Lassen Sie uns zuerst Seite an Seite arbeiten:
Derzeit generiert textInput zwei separate Tags - das
label
und dasinput
, von denen jedes von CSS als konfiguriert wird. Diesdisplay:block
bedeutet, dass es sich um ein Rechteck handelt, das auf der linken Seite des Containers unterbrochen wird . Wir müssen jedestextInput
Feld in einen neuen Container (div) einschließen und diesem Container mitteilen, dass sich der darauf folgende Container (der nächstetextInput
) mithilfe von CSS in derselben horizontalen Zeile auf der Seite befinden darfdisplay:inline-block
.Also fügen wir jedem einen Div mit einem Stil hinzu
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) {} ))
Kleine Eingänge
Jetzt beschäftigen wir uns mit kleinen. Es gibt ein paar Möglichkeiten, klein zu machen,
Da
bootstrap.js
wir bei der Verwendung von Shiny wirklich die Kontrolle über das Layout haben, funktionieren nur 3 zuverlässig. Lassen Sie uns das verwenden.Die Eingabegrößen sind in der CSS Forms-Dokumentation von Bootstrap 2.3.2 unter "Control Sizing" dokumentiert . Es enthält eine Vielzahl von Größen von Mini, Klein, Mittel, Groß, Xlarge und Xxlarge. Die Standardeinstellung ist wahrscheinlich Medium. Versuchen wir es stattdessen klein.
Um die Größe festzulegen, müssen wir die Klasse des von
input
generierten Tags änderntextInput
.Jetzt
textInput
ist nur eine Komfortfunktion um die leistungsstärkerentags
Funktionen wietags$label
undtags$input
. Wir können eine leistungsfähigere Version davon erstellentextInput
, mit der wir die Elemente konfigurieren können, insbesondere die Klasse desinput
Knotens: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) {} ))
Und wir sind fertig - aber wir können einige dieser Funktionen zusammenfassen, indem wir
textInput3
das div-Tag generiert haben. Es könnte auch die Klasse selbst festlegen, aber das überlasse ich Ihnen zum Schreiben.Verpacken
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) {} ))
Aus Gründen des Interesses ist hier die Version mit Klasse
input-mini
:quelle
Mit Shiny (> = 0.11) können Sie dies erreichen, indem Sie die Eingabeaufrufe in ein splitLayout () einfügen . Dadurch werden die flüssige Zeile, das Feld usw. in die erforderlichen Spalten aufgeteilt, die erforderlich sind, um Ihre Eingabefelder nebeneinander anzuzeigen.
Das folgende Beispiel gibt Ihnen drei Texteingaben in einem Feld, die nebeneinander in der fluidRow angezeigt werden.
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") ) ) )
quelle
box
ist aus demshinydashboard
PaketVielleicht gab es diese Lösung 2013 nicht, aber wenn Sie dies tun möchten, ohne HTML oder CSS zu schreiben, können Sie die
column
Funktion einfachfluidRow
so verwenden:fluidRow( column(3, selectInput('pcat', 'Primary Category', c("ALL", "Some"))), column(3, selectInput('smodel', 'Statistical Model', c("NONE", "LINEAR REGRESSION", "LOWESS"))) )
Und es wird die Dinge nebeneinander stellen.
EDIT: Jetzt gibt es eine andere sehr einfache Möglichkeit, dies mit der
splitLayout()
Funktion zu tun . Weitere Informationen finden Sie in der Antwort von Nadir Sidi.quelle
Ich habe die alte Antwort gelöscht - hier ist eine, die funktioniert:
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}")) )) ))
Hier sind die Änderungen, die ich vorgenommen habe:
1) Ich habe das
select
ausselect#xlimitsmax
undselect#xlimitsmin
in Ihren.css
Aussagen beseitigt2) Ich habe Ihre beiden Steuerelemente jeweils einzeln aufgeführt
div()
und ihnen die NamenXXmin
und gegebenXXmax
. Ich habe dann hinzugefügt.css
Anweisungen , um sie inline-block zu machen.Wenn Sie eine Reihe von diesen haben, möchten Sie möglicherweise eine
class
Anweisung verwenden - wie zum Beispiel: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}")),
Dann können Sie jedes Steuerelement
div()
als kennzeichnenclass="MyClass"
und nur eine.css
Anweisung verwenden.Bearbeitet, um hinzuzufügen: Vielen Dank, dass Sie den Beispielcode veröffentlicht haben - das hat es viel einfacher gemacht.
2. Bearbeitung: Nur zur Klarstellung. Der Zweck des Einfügens der
textInput
Befehle in adiv()
besteht darin, das Eingabefeld und seine Beschriftung in einem einzigen Objekt zu vereinen, damit Stile (in diesem Fall derdisplay
Stil) angewendet werden können. Wenn Sie dies nicht tun, fungieren das Etikett und das Feld als zwei separate Einheiten, und es ist in solchen Fällen schwieriger, sie zu manipulieren.quelle
Als Alternative zum Einfügen ausführlicher Stildeklarationen in eine Klasse können Sie die Funktionen für glänzende Tags anscheinend problemlos nach Ihren Wünschen erweitern. Dieser spezielle wäre standardmäßig praktisch. (Dies ist mit glänzend glänzend_0.14.1). Ich dachte, ich müsste einen Abschluss schreiben, aber das scheint zu funktionieren.
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)),
quelle
Wenn Sie die Eingaben in mainPanel möchten, können Sie Folgendes verwenden:
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)) )
Hinzufügen:
#xlimitsmin, #xlimitsmax, #ylimitsmin, #ylimitsmax { max-width: 25px; }
in einer CSS-Datei (z. B. style.css im Verzeichnis www /) in Ihrer App und beziehen Sie sie von ui.R mit:
includeCSS ('www / style.R')
Ich bin mir nicht sicher, warum Sie einen textInput anstelle eines numericInput benötigen, da die Eingabe, nach der Sie zu suchen scheinen, numerisch ist. Wenn Sie numericInput wählen, können Sie textInput oben einfach durch numericInput ersetzen. Wenn Sie die Eingaben im sidebarPanel möchten, können Sie den folgenden Code verwenden. Die gleiche CSS-Datei, die oben erwähnt wurde, wäre erforderlich.
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)) )
quelle
Ich war nicht zufrieden damit,
splitLayout()
weil es Bildlaufleisten einführt, wenn der Platz begrenzt ist.Ich fand heraus, dass zumindest für Eingabe-Widgets wie Schaltflächen oder Textfelder eine recht einfache Lösung mit besserem Reaktionsverhalten die Verwendung von Flexboxen ist: (siehe diese großartige Anleitung: 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") ) )
Es ist möglich, relative Breiten anzupassen. Entspricht
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") ) )
quelle
Sgrubsmyons Ansatz war für mich fast perfekt, aber ich stieß auf ein neues Problem mit dem Flex-Box-Ansatz, da zwischen den Eingängen keine Auffüllung bestand. Anscheinend hat dies etwas damit zu tun, dass "display: flex" ein Wrapper für "flex-grow 1" ist, der den gesamten verfügbaren Speicherplatz belegt. Ich tauchte in das Kaninchenloch ein und konnte dies nicht zum Laufen bringen, lernte aber einen ähnlichen Ansatz kennen, der "CSS - Grid" verwendet und noch einfacher ist (relevante SO-Frage, aus der ich dies gelernt habe) :
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") )
Für den hier befindlichen CSS-Grid-Ansatz gibt es eine ähnlich gute Anleitung , in der Sie mehr über die verschiedenen Argumente und Anpassungsmöglichkeiten erfahren, die Sie verwenden können. Beachten Sie, dass ich CSS erst 2 Stunden vor dem Schreiben dieser Antwort berührt habe, daher sind Korrekturen willkommen =)
quelle