1

The following attempts to put Shiny fileInput() and textInput() side by side.

A simple server.R file:

shinyServer(function(input, output) {} )

And the following ui.R:

# Custom function(s) to get file- and text-Input side by side
# Based on: <http://stackoverflow.com/a/21132918/1172302>

# options(shiny.error=browser)

# Globals

display.inline.block <- "display:inline-block"
class.input.small = "input-small"
FileInputId <- "SampleFile"
FileInputLabel <- "Sample"
TextInputId <- "SampleLabel"
TextInputLabel <- "Label"
TextInputLabelDefault <- "Sample Label"

# helper functions

fileInput.custom <- function (inputId, label, ...)
{
    tagList(tags$label(label, `for` = inputId),
            tags$input(id = inputId, type = "file", ...)
    )
}

textInput.custom <- function (inputId, label, value = "",...) 
{
    tagList(tags$label(label, `for` = inputId),
            tags$input(id = inputId, type = "text", value = value,...)
    )
}

filetextInput <- function (fileId, fileLabel, textId, textLabel, textValue, divstyle, ...)
{

    # sample file
    div(style = divstyle,
        fileInput.custom(inputId = fileId,
                      label = fileLabel,
                      class = class.input.small))

    # label for sample, to be used in plot(s)
    div(style = divstyle,
        textInput.custom(inputId = textId,
                      label = textLabel,
                      value = textValue,
                      class = class.input.small))

}

# Shiny UI

shinyUI(
  fluidPage(

    # sample input
    div(style = display.inline.block,
      fileInput.custom(inputId = FileInputId,
                label = FileInputLabel)
    ),

    # label for sample 
    div(style = display.inline.block,
      textInput.custom(inputId = TextInputId,
                label = TextInputLabel,
                value = TextInputLabelDefault)
    ),

    hr(),

    filetextInput(
        fileId = FileInputId,
        fileLabel = FileInputLabel,
        textId = TextInputId,
        textLabel = TextInputLabel,
        textValue = TextInputLabelDefault,
        divstyle = display.inline.block)

  )
)

The above results in:

Attempt(s) to put fileInput and textInput side-by-side

As shown in the screenshot, it works using two separate divs. Why doesn't it work in the case of the filetextInput() function?

Nikos Alexandris
  • 708
  • 2
  • 22
  • 36
  • Based on http://stackoverflow.com/a/21132918/1172302 – Nikos Alexandris Jan 05 '16 at 10:57
  • 1
    Wrap the body of fileTextInput in a tagList or div. – Alex Brown Jan 05 '16 at 18:59
  • Kind of related -- Being heavily influenced by Python, I read in https://www.oreilly.com/ideas/how-to-make-mistakes-in-python?utm_source=social&utm_medium=twitter&utm_content=20160406-new-site-python-mistakes-report-post&utm_campaign=radar_tweet the following: _I’m fairly certain that a majority of my hours spent debugging mysterious problems were due to this one simple mistake: forgetting to return a value from a function._ – Nikos Alexandris Apr 13 '16 at 06:08

1 Answers1

3

Functions return the last evaluated value, so in your case the first part is lost. E.g. :

function(){
"a"
"b"
}

returns "b"

so you don't want that. Use a div or a tagList.

filetextInput <- function (fileId, fileLabel, textId, textLabel, textValue, divstyle, ...)
{
  div(
  # sample file
  div(style = divstyle,
      fileInput.custom(inputId = fileId,
                       label = fileLabel,
                       class = class.input.small)
      ),

  # label for sample, to be used in plot(s)
  div(style = divstyle,
      textInput.custom(inputId = textId,
                       label = textLabel,
                       value = textValue,
                       class = class.input.small)
      )
  )

}
fxi
  • 607
  • 8
  • 16
  • And think that the resulting html will be evaluated in the browser : use a css file and/or bootstrap classes like ".form-inline" outside ui.R, e.g. www/my.css – fxi Jan 05 '16 at 11:27
  • Ah, right another `div`. Thanks. --ps I always wonder why people reply to questions and don't upvote them :-p – Nikos Alexandris Jan 05 '16 at 12:54
  • I don't really know when I should upvote a question, sorry. But I suppose that a challenging, clear and non trivial question could deserve an upvote. Here, this is a question about how functions work, not a huge deal. But as you provided a full example, this could deserve a click ;) – fxi Jan 05 '16 at 13:12
  • It was really a generic question -- my mistake, I should ask this in meta or else. Thanks anyway. – Nikos Alexandris Jan 05 '16 at 13:29