Context: I am trying to make a shiny feature where the user can upload txt files and view the content of the files as a table. To account for the different types of delimiters I have placed radio buttons to act as delimiter options. The radio buttons will depend on the file type uploaded.
Issue: The user would not be able to change the delimiter options and display the respective table, because the server keeps checking the file type and changing the radio buttons and resetting the default button.
Attempted solutions:
- Setup a radiobutton for the user to select the file type which changes the delimited buttons instead of using an if condition of file type to determine the delimiter radiobuttons. Solution is not user friendly since the program should be able to identify and modify the radiobuttons in accordance to the file type.
- Setup a go button to perform the if conditions for file type instead of relying on the server looping. Couldn't implement it properly
Question: Can anyone suggest solutions that are user friendly? Is there a feature in R shiny that already solves this issue?
UI
library(shinyWidgets)
library(DT)
library(shiny)
ui <- fluidPage(
titlePanel(title=div(img(src="ODClogo.png", height = 50), "OutDeCo")),
#navbarPage is top menu bar
navbarPage("",
#tabPanel is each tab in the navbarPage
# Assess DE tab
tabPanel(
title="Assess DE",
dropdown(
# title of sidepanel
tags$h3("Options"),
# inputs in the sidepanel
fileInput("DEFile", "Choose DE File",
accept = c(
".csv",
".tsv",
".txt"
)
),
# button for selecting delimiter, default is nothing until file is selected and handled in server side
radioButtons(inputId = 'sepButton', label = 'Delimiter Selector', choices = c(Default=''), selected = ''),
# side panel characteristics
style = "gradient", icon = icon("cog"),
status = "primary", width = "300px",
animate = animateOptions(
enter = animations$fading_entrances$fadeInLeftBig,
exit = animations$fading_exits$fadeOutLeftBig
)
),
navlistPanel(
tabPanel(
title="Cluster Genes",
"Cluster genes Page",
# Navigation Bar for types of plots inside cluster
tabsetPanel(
tabPanel(
title="View file",
mainPanel(
uiOutput("UIDEContent")
)
),
tabPanel(
title="Plot 2"
),
tabPanel(
title="Plot 3"
)
),
),
),
)
),
)
Server
server <- function(input, output, session) {
output$distPlot <- renderPlot({
hist(rnorm(input$obs), col = 'darkgray', border = 'white')
})
# reactive converts the upload file into a reactive expression known as data
data <- reactive({
# DEFile from fileInput() function
ServerDEFile <- input$DEFile
# extensions tool for format validation
extDEFile <- tools::file_ext(ServerDEFile$datapath)
# file format checking
req(ServerDEFile)
validate(need(extDEFile == c("csv", "tsv", "txt"), "Please upload a csv, tsv or txt file."))
# convert data into file format
if(is.null(extDEFile)){return()}
if (extDEFile == "txt") {
choice <-c(Comma=",", Semicolon=";", Tab="\t", Space=" ")
updateRadioButtons(session, "sepButton",
label = paste("Delimiters for", extDEFile, "file"),
choices = choice,
)
}
else if (extDEFile == "tsv") {
choice <- (Tab="\t")
updateRadioButtons(session, "sepButton",
label = paste("Delimiter: Tab"),
choices = choice
)
}
else {
choice <- (Comma=",")
updateRadioButtons(session, "sepButton",
label = paste("Delimiter: Comma"),
choices = choice
)
}
read.table(file=ServerDEFile$datapath, sep=input$sepButton)
})
# creates reactive table called DEFileContent
output$DEFileContent <- renderTable({
if(is.null(data())){return ()}
data()
})
# handles rendering of reactive object on tb on ui
output$UIDEContent <- renderUI({
tableOutput("DEFileContent")
})
}
CodePudding user response:
Use reactive
object just to create a data frame, and use an observe
r to update radio button. Try this
library(shinyWidgets)
library(DT)
library(shiny)
ui <- fluidPage(
titlePanel(title=div(img(src="ODClogo.png", height = 50), "OutDeCo")),
#navbarPage is top menu bar
navbarPage("",
#tabPanel is each tab in the navbarPage
# Assess DE tab
tabPanel(
title="Assess DE",
dropdown(
# title of sidepanel
tags$h3("Options"),
# inputs in the sidepanel
fileInput("DEFile", "Choose DE File",
accept = c(
".csv",
".tsv",
".txt"
)
),
# button for selecting delimiter, default is nothing until file is selected and handled in server side
radioButtons(inputId = 'sepButton', label = 'Delimiter Selector', choices = c(Default=''), selected = ''),
# side panel characteristics
style = "gradient", icon = icon("cog"),
status = "primary", width = "300px",
animate = animateOptions(
enter = animations$fading_entrances$fadeInLeftBig,
exit = animations$fading_exits$fadeOutLeftBig
)
),
navlistPanel(
tabPanel(
title="Cluster Genes",
"Cluster genes Page",
# Navigation Bar for types of plots inside cluster
tabsetPanel(
tabPanel(
title="View file",
mainPanel(
uiOutput("UIDEContent")
)
),
tabPanel(
title="Plot 2"
),
tabPanel(
title="Plot 3"
)
),
),
),
)
),
)
server <- function(input, output, session) {
output$distPlot <- renderPlot({
hist(rnorm(input$obs), col = 'darkgray', border = 'white')
})
observe({
# DEFile from fileInput() function
ServerDEFile <- req(input$DEFile)
# extensions tool for format validation
extDEFile <- tools::file_ext(ServerDEFile$datapath)
if(is.null(input$DEFile)){return()
}else{
if (extDEFile == "txt") {
label = paste("Delimiters for", extDEFile, "file")
choice <-c(Comma=",", Semicolon=";", Tab="\t", Space=" ")
}else if (extDEFile == "tsv") {
label = paste("Delimiter: Tab")
choice <- (Tab="\t")
}else {
label = paste("Delimiter: Comma")
choice <- (Comma=",")
}
updateRadioButtons(session, "sepButton", label = label, choices = choice)
}
})
# reactive converts the upload file into a reactive expression known as data
data <- reactive({
# DEFile from fileInput() function
ServerDEFile <- input$DEFile
# extensions tool for format validation
extDEFile <- tools::file_ext(ServerDEFile$datapath)
# file format checking
req(ServerDEFile)
validate(need(extDEFile == c("csv", "tsv", "txt"), "Please upload a csv, tsv or txt file."))
# convert data into file format
if(is.null(extDEFile)){return()}
read.table(file=ServerDEFile$datapath, sep=input$sepButton)
})
# creates reactive table called DEFileContent
output$DEFileContent <- renderTable({
if(is.null(data())){return ()}
data()
})
# handles rendering of reactive object on tb on ui
output$UIDEContent <- renderUI({
tableOutput("DEFileContent")
})
}
shinyApp(ui = ui, server = server)