Piet93
Piet93

Reputation: 179

Using input to create UI in Shiny R

I am building an app in shiny (R). At the beginning the user can upload a file to use (I am doing a sort data analysis). My goal is to be able to use files without knowing how many columns this file has, and how the data exactly looks like.

So now I have to select the columns by number, and I made a small preview app for this to select columns and then display them next to the original:

library(shiny)

ui <-fluidPage(
  headerPanel("Select data"),
  sidebarLayout(
sidebarPanel(
  fileInput("uploadFile", "XLSX file"),

  textInput('vec1', 'Choose training columns', "3,4"),
  actionButton("choose","choose data")
),
mainPanel(
  fluidRow(
    column(6,tableOutput("data_raw")),
    column(6,tableOutput("data_selected"))
  )
  )
 )
 )


server <- function(input, output) {



  output$data_raw <- renderTable({

    inFile <- input$uploadFile
    if (is.null(inFile))
     return(NULL)

     data_raw <<-read.xlsx(inFile$datapath, 1)
  })

  observe({
    if(input$choose>0){
     selectvec <- as.numeric(unlist(strsplit(input$vec1,",")))

     output$data_selected <- renderTable(
      data_selected<- data_raw[,selectvec]
     )
    }
   })
  }


shinyApp(ui,server)

Now I would like to be able to select the columns to use on basis of their header.

It feels unnatural: changing the app while running.. but in a reactive environment.. why not?

QUESTION: How can I change the UI while it is allready running, with values originating from the input?

kind regards, Pieter

Upvotes: 0

Views: 131

Answers (1)

Carl Boneri
Carl Boneri

Reputation: 2722

To make me feel not as dirty for answering this...I didn't debug or handle reactives properly. But here ya go. You need to respond to the file that is uploaded on the server side, extract the column names, and append thosed to the choices in a select input that then passes down to the table function as a column filter.

 upload_app <- function(){
  library(shiny)

  ui <- bootstrapPage(
    tags$div(class = "container",
             column(3,
                    fluidRow(
                      fileInput(inputId = 'user_data',
                                label = 'Upload Data (csv)',
                                multiple = FALSE,
                                accept =  c(
                                  'text/csv',
                                  'text/comma-separated-values',
                                  'text/tab-separated-values',
                                  'text/plain',
                                  '.csv',
                                  '.tsv'
                                ))
                    ),
                    fluidRow(
                      uiOutput('column_vars')
                    )
             ),
             column(9,
                    tableOutput('filtered_table'))
    )
  )

  server <- function(session, input, output){

    var_table <- reactive({
      var_data <- input$user_data
      read.csv(var_data$datapath, header = TRUE,sep = ",", quote = '')
    })

    output$column_vars <- renderUI({
      if(!is.null(var_table())){
      selectInput(inputId = 'cols',
                  choices = colnames(var_table()),
                  multiple = T,
                  label = "Choose Columns")
      }
    })

    output$filtered_table <- renderTable({

      if(!is.null(var_table())){
        if(length(input$cols)>0){
          get_these <- input$cols
          new_table <- var_table()[,c(get_these)]
        }else {
          new_table <- var_table()
        }

      }else {
        new_table <- data.frame(data = 'Waiting')
      }

      return(new_table)

    })
  }

  shinyApp(ui, server)

}

enter image description here

Upvotes: 1

Related Questions