glimmende 4 kleine tekstInvoervakken naast elkaar

Ik heb een glanzende serverversie 0.4.0 en ik wil 4 kleine tekstinvoervakken hebben die er als volgt uitzien:

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

Ze zien er nu zo uit:

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

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

Enig idee hoe dit te bereiken?

BEWERKT: Ik heb dit soort dingen elders in de code met succes gewijzigd:

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

En zo ziet het eruit voor degenen die niet werken:

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

BEWERKT:

Hier is een op zichzelf staand voorbeeld ui.Rdat niet werkt:

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

Resulterende pagina:

voer hier de afbeeldingsbeschrijving in


Antwoord 1, autoriteit 100%

om te parafraseren (en om te vereenvoudigen tot het geval van 2 ingangen), uw probleem is dat:

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

shows

voer hier de afbeeldingsbeschrijving in

Maar je wilt kleine invoer naast elkaar, zoals:

kleine rij

Het korte antwoord

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

geeft:

voer hier de afbeeldingsbeschrijving in

Het lange antwoord

Side-by-side inputs

Laten we eerst zij aan zij doen:

Momenteel genereert textInput twee afzonderlijke tags – het labelen de input, die elk door CSS zijn geconfigureerd als display:block, wat betekent dat het een rechthoek is die aan de linkerkant van de container zal breken. We moeten elk veld van textInputin een nieuwe container (div) plaatsen en die container vertellen dat de container die erop volgt (de volgende textInput) op de dezelfde horizontale rij op de pagina, met behulp van CSS’s display:inline-block.

Dus we voegen een div toe met een stijl rond elke 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) {}
))

rij

Kleine ingangen

Laten we het nu hebben over klein. Er zijn een paar manieren om klein te doen,

  1. maak het lettertype kleiner,
  2. zorg ervoor dat het invoervak ​​minder tekens bevat.
  3. vertel css of (hier) bootstrap om een ​​kleiner vak te tekenen

Aangezien bootstrap.jsde lay-out echt onder controle heeft wanneer we shiny gebruiken, zullen er maar 3 betrouwbaar werken, dus laten we die gebruiken.

Invoergroottes worden gedocumenteerd in Bootstrap 2.3.2’s CSS Forms-documentatie, onder ‘Control Sizing’. Het bevat verschillende formaten, van mini, small, medium, large, xlarge en xxlarge, en de standaard is waarschijnlijk medium. Laten we het in plaats daarvan klein proberen.

Om de grootte in te stellen, moeten we de klasse wijzigen van de input-tag die wordt gegenereerd door textInput.

Nu is textInputslechts een gemaksfunctie rond de krachtigere tags-functies zoals tags$labelen tags$input. We kunnen een krachtigere versie van textInputbouwen waarmee we de elementen kunnen configureren, met name de klasse van het input-knooppunt:

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

kleine rij

En we zijn klaar – maar we kunnen een deel van deze functionaliteit oprollen door textInput3de div-tag te laten genereren. Het kan ook de klasse zelf instellen, maar dat laat ik aan jou over om te schrijven.

Het afronden

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

Voor de interesse, hier is de versie met class input-mini:

voer hier de afbeeldingsbeschrijving in


Antwoord 2, autoriteit 83%

Met Shiny (>= 0.11) kunt u dit bereiken door de invoeraanroepen in een splitLayout(). Hierdoor wordt de rij, het vak, enz. opgesplitst in de benodigde kolommen om uw invoervelden naast elkaar weer te geven.

Het onderstaande voorbeeld geeft u drie tekstinvoer in een vak, die naast elkaar in de fluidRow zal verschijnen.

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

Antwoord 3, autoriteit 36%

Misschien was deze oplossing er nog niet in 2013, maar als je dit wilt doen zonder HTML of CSS te schrijven, kun je gewoon de functie columngebruiken binnen een fluidRowzoals zo :

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

En het zal dingen naast elkaar plaatsen.

EDIT: Er is nu een andere, zeer gemakkelijke manier om dit te doen met de functie splitLayout(). Zie het antwoord van Nadir Sidi voor meer details.


Antwoord 4, autoriteit 6%

Ik heb het oude antwoord verwijderd – hier is er een die werkt:

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

Dit zijn de wijzigingen die ik heb aangebracht:

1) Ik heb de selectuit select#xlimitsmaxen select#xlimitsminverwijderd in je .css-statements

2) Ik heb je twee besturingselementen elk in hun eigen div()gezet en ze de namen XXminen XXmaxgegeven. Vervolgens heb ik .cssstatements toegevoegd om ze inline-block te maken.

Als je er een aantal hebt, wil je misschien een class-statement gebruiken, zoals:

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

dan kun je elk van de controle div()‘s taggen als class="MyClass"en slechts één .css-statement gebruiken .

Bewerkt om toe te voegen: bedankt voor het plaatsen van de voorbeeldcode – dat maakte het veel gemakkelijker.

2e bewerking: even ter verduidelijking. Het punt van het plaatsen van de textInput-commando’s in een div()is om het invoervak ​​en zijn label te verenigen in een enkel object, zodat stijlen (in dit geval de displaystijl) kan worden toegepast. Als u dit niet doet, fungeren het label en de doos als twee afzonderlijke entiteiten en is het moeilijker om ze in dit soort gevallen te manipuleren.


Antwoord 5, autoriteit 6%

Als alternatief voor het plaatsen van uitgebreide stijldeclaraties in een klasse, lijkt het erop dat je de glanzende tags-functies gemakkelijk naar wens kunt uitbreiden. Deze specifieke zou handig zijn om standaard bij de hand te hebben.
(dit is met shiny shiny_0.14.1 ). Dacht dat ik een afsluiting moest schrijven, maar dit lijkt te werken.

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

Antwoord 6, autoriteit 3%

Ik was niet blij met splitLayout()omdat het schuifbalken introduceert wanneer de ruimte beperkt is.

Ik ontdekte dat, in ieder geval voor invoerwidgets zoals knoppen of tekstvakken, een vrij eenvoudige oplossing met beter responsief gedrag het gebruik van flex-box is: (zie deze geweldige gids: 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")
  )
)

Het is mogelijk om relatieve breedtes aan te passen. Overeenkomend met 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")
  )
)

Antwoord 7, autoriteit 2%

Als u de invoer in het hoofdpaneel wilt, kunt u het volgende gebruiken:

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

Toevoegen:

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

in een css-bestand (bijv. style.css in de www/-directory) in uw app en bron het van ui.R met:

includeCSS(‘www/style.R’)

Ik weet niet zeker waarom je een tekstinvoer nodig hebt in plaats van een numerieke invoer, aangezien de invoer waarnaar je lijkt te zoeken numeriek is. Als u numericInput kiest, kunt u in het bovenstaande eenvoudig textInput vervangen door numericInput. Als u de invoer in het zijbalkpaneel wilt, kunt u de onderstaande code gebruiken. Hetzelfde css-bestand als hierboven vermeld zou nodig zijn.

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

Antwoord 8, autoriteit 2%

De aanpak van Sgrubsmyon was bijna perfect voor mij, maar ik kwam een ​​nieuw probleem tegen met de flex-box-aanpak doordat er geen opvulling was tussen de ingangen. Blijkbaar heeft dit iets te maken met “display: flex” dat een wrapper is voor “flex-grow 1” die alle beschikbare ruimte in beslag neemt. Ik dook in het konijnenhol en kon dit niet laten werken, maar leerde over een vergelijkbare aanpak die gebruik maakt van “CSS – Grid” en nog eenvoudiger is (relevante SO-vraag waar ik dit van heb geleerd):

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

Er bestaat een vergelijkbare geweldige gids voor de CSS – Grid-aanpak die hier< te vinden iswaar u meer te weten kunt komen over alle verschillende argumenten en aanpasbaarheid die u kunt gebruiken. Merk op dat ik CSS nooit heb aangeraakt tot 2 uur voordat ik dit antwoord schreef, dus eventuele correcties zijn welkom =)

Other episodes