1

I am using R shiny and my app is built to read in a file from the user for manipulation later. I want to try and use the fileInput() command but I don't want to see the loading bar next to the browse option. Is there any way to get rid of it or hide it so that it just looks like a button? Also, can I rename the default "Browse" to something else, like "load"?

Alternatively, I think I would be interested in having an action button that get pushed and then calls the inputFile() command but I am having a hard time implementing that.

The ultimate goal is that I want the user to be able to push a button that says load and then this triggers some sort of window to pop-up that allows the user to upload a file, but I only want to see a button on the front page of the inputs.

RustyStatistician
  • 989
  • 3
  • 14
  • 25

1 Answers1

6

The input of type "file" is controlled and defined by your browser, so there is nothing you can do from the Shiny side to modify the appearance, but you can hide it.

The file input will react also to the Label, so you can modify the appearance of the label as much as you want.

The first step is to create your own version of the fileinput function. This new function will hide the tags$input using CSS and will customize the Label and optionally remove the progress bar.

Below is the code with two file inputs as a button with custom text and icon, also with and without the progress bar.

library(shiny)

# based on the Shiny fileInput function
fileInput2 <- function(inputId, label = NULL, labelIcon = NULL, multiple = FALSE, 
                       accept = NULL, width = NULL, progress = TRUE, ...) {
  # add class fileinput_2 defined in UI to hide the inputTag
  inputTag <- tags$input(id = inputId, name = inputId, type = "file", 
                         class = "fileinput_2")
  if (multiple) 
      inputTag$attribs$multiple <- "multiple"
  if (length(accept) > 0) 
      inputTag$attribs$accept <- paste(accept, collapse = ",")

  div(..., style = if (!is.null(width)) paste0("width: ", validateCssUnit(width), ";"), 
    inputTag,
    # label customized with an action button
    tags$label(`for` = inputId, div(icon(labelIcon), label, 
                class = "btn btn-default action-button")),
    # optionally display a progress bar
    if(progress)
      tags$div(id = paste(inputId, "_progress", sep = ""), 
        class = "progress shiny-file-input-progress", 
        tags$div(class = "progress-bar")
      )
  )
}          


ui <- fluidPage(
  # define class fileinput_2 to hide inputTag in fileInput2
  tags$head(tags$style(HTML(
    ".fileinput_2 {
      width: 0.1px;
      height: 0.1px;
      opacity: 0;
      overflow: hidden;
      position: absolute;
      z-index: -1;
    }"
  ))),
  sidebarLayout(
    sidebarPanel(
      h3("Without progress bar"),  
      fileInput2("file1", "Load File 1", labelIcon = "folder-open-o", 
          accept = c("text/csv",
            "text/comma-separated-values,text/plain",
            ".csv"), progress = FALSE),
      h3("With progress bar"),
      fileInput2("file2", "Load File 2", labelIcon = "file-code-o", 
          accept = c("text/csv",
            "text/comma-separated-values,text/plain",
            ".csv"), progress = TRUE)
    ),
    mainPanel(
       verbatimTextOutput("content1"),
       verbatimTextOutput("content2")
    )
  )
)

server <- function(input, output) {
  output$content1 <- renderPrint({
    inFile <- input$file1
    if (is.null(inFile))
      return(NULL)
    paste("File name 1:", inFile$name)
  })
  output$content2 <- renderPrint({
    inFile <- input$file2
    if (is.null(inFile))
      return(NULL)
    paste("File name 2:", inFile$name)
  })
}

shinyApp(ui, server)

enter image description here

Geovany
  • 5,389
  • 21
  • 37
  • Thanks, that works perfectly! One last question, originally I had two action buttons side by side using your solution here: http://stackoverflow.com/questions/40537917/how-to-place-buttons-in-shiny/40538274#40538274 I am still suing that setup, but now I want to have the button from this question next to the button from the other question. Is that easily doable? – RustyStatistician Nov 16 '16 at 15:04
  • Actually I figured out a work around so don't worry. – RustyStatistician Nov 16 '16 at 15:18
  • Thank you very much for this solution! May I ask you how you would remove the border width of this new button? If I use the standard CSS code by specifying the inputId (`#file1 {border-width: 0px;}` nothing happens. – nd091680 Dec 11 '19 at 16:07