How to reset an ui in shiny? - r

I created an actionButton RUN demo data as a demonstration of an app and I am wondering how to reset it all so that the user can start his input for user's data sets. I looked around the reset button but still can't get it through.
rm(list=ls())
library(tidyverse)
library(shiny)
# Define UI ----
ui <- fluidPage(
tabsetPanel(
#tabPanel-Input
tabPanel("Input", fluid = TRUE,
# tab title ----
titlePanel("Upload data"),
# sidebar layout with input and output tables ----
sidebarLayout(
# sidebar panel for inputs ----
sidebarPanel(
#show ct demo
actionButton("runexample", "RUN demo data"),
# input1: Select a file ----
fileInput("file1", "Count matrix File (.xlsx)",
multiple = TRUE,
accept = c("text/csv",
"text/comma-separated-values,text/plain",
".csv")),
#input2: select a file ----
fileInput("file2", "Manifest File (.xlsx)",
multiple = TRUE,
accept = c("text/csv",
"text/comma-separated-values,text/plain",
".csv")),
#select column name
selectInput("design", "Column name for analysis", " "),
#select ref group
uiOutput("level0"),
#select study group
uiOutput("level1"),
#action run
actionButton("runbutton", "Run"),
#comment message
p("Click to perform differential gene expression analysis between the selected groups"),
#README link
uiOutput("README"),
#issue report
uiOutput("issue")
),
# Main panel for displaying outputs ----
mainPanel(
# Output: Data file ----
tableOutput("matrix"),
tableOutput("pdat")
)
)
),
#tabPanel-Results
tabPanel("Results", fluid = TRUE,
# App title ----
titlePanel("Download results"),
# Sidebar layout with input and output definitions ----
sidebarLayout(
# Sidebar panel for inputs ----
sidebarPanel(
# Input: Choose dataset ----
selectInput("results", "Choose a dataset:",
choices = c("Results", "Normalized matrix")),
# Button
downloadButton("downloadData", "Download")
),
# Main panel for displaying outputs ----
mainPanel(
tableOutput("table")
)
)
),
#tabPanel-Plots
tabPanel("Plots", fluid = TRUE,
fluidRow(
column(width = 8,
plotOutput("plot1", height = 800,
# Equivalent to: click = clickOpts(id = "plot_click")
click = "plot1_click",
brush = brushOpts(
id = "plot1_brush"
)
)
),
column(width = 4,
h4("Brushed points"),
verbatimTextOutput("brush_info")
)
)
)
)
)
# Define Server ----
server <- function(input, output, session) {
#tabPanel-Input
###demo data
####count
set.seed(123)
ctdemo<- t(rmultinom(1000, size = 50, prob = c(rep(0.4, 4), rep(0.6, 4))))
####manifest
pdemo<-data.frame(Samples=paste0("Sample", 1:8),
Treatment=rep(c("DrugA", "DrugB"), each=4))
###display demo count matrix
observeEvent(input$runexample, {
output$matrix <- renderTable({
head(ctdemo, 10)
})
output$pdat <- renderTable({
head(pdemo, 10)
})
observe({
updateSelectInput(session, "design", choices="Treatment")
})
output$level0 <- renderUI({
selectInput("ref0", "Reference group", "DrugA")
})
output$level1 <- renderUI({
selectInput("ref1", "Study group", "DrugB")
})
})
}
shinyApp(ui, server)

Actually you've made most of the job (I don't copy-paste the full code, it is quite long and the solution is short).
First, create the button "Reset" in the ui part with actionButton("reset", "Reset"), (I placed it just after the button runexample).
Then, put almost of the code of the server part in an observeEvent that is triggered with reset (place this chunk of code at the end of the server part):
observeEvent(input$reset, {
output$matrix <- renderTable(NULL)
output$pdat <- renderTable(NULL)
observe({
updateSelectInput(session, "design")
})
output$level0 <- renderUI(NULL)
output$level1 <- renderUI(NULL)
})
That's it !

Related

How to filters across multiple tabs R Shiny

I'm creating a R Shiny App that contains three tabs. I would like to display a filter on the first two tabs and no filter on the third tab. I would like the filter on tabs one and two to be synchronized.
library(shiny)
server <- function(input, output, session) {
dataset <- reactive({
get(input$dataset, "package:datasets")
})
output$summary <- renderPrint({
summary(dataset())
})
output$table <- renderTable({
dataset()
})
output$table_head <- renderTable({
head(dataset())
})
}
ui <- fluidPage(
tabsetPanel(type = "tabs",
tabPanel(title = "tab one filtered",
sidebarLayout(
sidebarPanel(
selectInput("dataset", label = "filter", choices = ls("package:datasets"))
),
mainPanel(
verbatimTextOutput("summary")
)
)
),
tabPanel(title = "tab two filtered",
sidebarLayout(
sidebarPanel(
selectInput("dataset", label = "filter", choices = ls("package:datasets"))
),
mainPanel(
tableOutput("table")
)
)
),
tabPanel(title = "tab three unfiltered",
mainPanel(
tableOutput("table_head")
)
)
)
)
shinyApp(ui, server)
My code is very similar to this. When I run this, the filter on the second page does not work. How can I display a synchronized filter on the first two tabs and no filter on the third tab. I've seen the suggestion to have the selectInput outside of the tabsetPanel but the filter will show on the third page. Thanks for the help.
You can't have two elements with the same ID in a given layout. So first you'll want to given them separate IDs
tabPanel(title = "tab one filtered",
sidebarLayout(
sidebarPanel(
selectInput("dataset1", label = "filter", choices = ls("package:datasets"))
),
mainPanel(
verbatimTextOutput("summary")
)
)
),
tabPanel(title = "tab two filtered",
sidebarLayout(
sidebarPanel(
selectInput("dataset2", label = "filter", choices = ls("package:datasets"))
),
mainPanel(
tableOutput("table")
)
)
),
then you'll need to do some extra work in the server to keep them insync.
server <- function(input, output, session) {
datasetname <- reactiveVal(ls("package:datasets")[1])
observeEvent(input$dataset1, {
updateSelectInput(session, "dataset2", selected=input$dataset1)
datasetname(input$dataset1)
})
observeEvent(input$dataset2, {
updateSelectInput(session, "dataset1", selected=input$dataset2)
datasetname(input$dataset2)
})
dataset <- reactive({
get(datasetname(), "package:datasets")
})
...
}
We keep a separate reactive value datasetname to keep track of the active name. Then we update the UI when one of the two dataset1/dataset2 values changes.

Subset data in R Shiny using Multiple Variables

I am new to R Shiny. I am attempting to create an app that allows a user to subset a data.frame based on multiple variables and then see the resulting data.
Here is a small example data set:
iter,wave,apples
1,1,600
1,1,500
1,1,400
1,2,300
1,2,200
1,2,100
2,1,1000
2,1,1100
2,1,1200
2,2,1300
2,2,1400
2,2,1500
3,1,1100
3,1,2200
3,1,3300
3,2,4400
3,2,5500
3,2,6600
I would like the user to be able to specify the value of iter and of wave and see the resulting data.
Here is my attempt at the Shiny code. I realize I must be making several silly mistakes.
Edit
Here is my revised code. The end result now comes pretty close to what I want. The sidebar is still not being displayed perfectly.
library(shiny)
setwd('C:/Users/mark_/Documents/simple_RShiny_files/explore')
apple.data <- read.csv('subset_data_based_on_multiple_variables.csv',
header = TRUE, stringsAsFactors = FALSE)
ui <- fluidPage(
titlePanel("Subsetting Apple Dataset"),
sidebarLayout(
sidebarPanel(
uiOutput("codePanel")
),
mainPanel(
tableOutput("view")
)
),
selectInput("codeInput", inputId ="data1", label = "Choose Iter", choices = unique(apple.data$iter)),
selectInput("codeInput", inputId ="data2", label = "Choose Wave", choices = unique(apple.data$wave))
)
server <- function(input, output) {
output$codePanel <- renderUI({
})
dataset <- reactive({
subset(apple.data, (iter == input$data1 & wave == input$data2))
})
output$view <- renderTable(dataset())
}
shinyApp(ui = ui, server = server)
The output
The problem is that both selectInputs have the same inputId. This works:
library(shiny)
apple.data <- data.frame(
iter = c(1L,1L,1L,1L,1L,1L,2L,2L,2L,2L,2L,
2L,3L,3L,3L,3L,3L,3L),
wave = c(1L,1L,1L,2L,2L,2L,1L,1L,1L,2L,2L,
2L,1L,1L,1L,2L,2L,2L),
apples = c(600L,500L,400L,300L,200L,100L,1000L,
1100L,1200L,1300L,1400L,1500L,1100L,2200L,3300L,4400L,
5500L,6600L)
)
ui <- fluidPage(
titlePanel("Subsetting Apple Dataset"),
sidebarLayout(
sidebarPanel(
selectInput("codeInput1", label = "Choose Iter", choices = unique(apple.data$iter)),
selectInput("codeInput2", label = "Choose Wave", choices = unique(apple.data$wave))
),
mainPanel(
tableOutput("view")
)
)
)
server <- function(input, output) {
dataset <- reactive({
return(subset(apple.data, (iter == input$codeInput1 & wave == input$codeInput2)))
})
output$view <- renderTable(dataset())
}
shinyApp(ui = ui, server = server)

How to create a popup window for user to input information in R shiny?

Here is an example. What I want is that users can run the demo as many time as they want by DEMO button. However when they click Browse for uploading local data (not reset button as I demonstrated in the example), I would popup a window to let users input their name and state in two input boxes. In the below example, by click RESET, a single popup box will launch (may be not a proper way).
library(shiny)
library(shinyWidgets)
if (interactive()) {
# Display an important message that can be dismissed only by clicking the
# dismiss button.
shinyApp(
ui <- fluidPage(
tabsetPanel(
##tabPanel-Input
tabPanel("Input", fluid = TRUE,
# tab title ----
titlePanel("Upload data"),
# sidebar layout with input and output tables ----
sidebarLayout(
# sidebar panel for inputs ----
sidebarPanel(
#show ct demo
actionBttn("runexample", "DEMO", style="simple", size="sm", color = "primary"),
# input1: Select a file ----
fileInput("file1", "Count matrix File (.xlsx)",
multiple = TRUE,
accept = c("text/csv",
"text/comma-separated-values,text/plain",
".csv")),
#action run
actionBttn("runbutton", "GO", style="simple", size="sm", color = "primary"),
actionBttn("reset", "RESET", style="simple", size="sm", color = "warning"),
verbatimTextOutput(outputId = "reset"),
),
# Main panel for displaying outputs ----
mainPanel(
# Output: Data file ----
span(textOutput("nrows"),style="color:blue"),
span(textOutput("ncols"),style="color:blue"),
tableOutput("matrix"),
)
)
)
)
),
server = function(input, output, session) {
###display demo count matrix
observeEvent(input$runexample, {
#ngenes
output$nrows <- renderText({paste("Number of genes: ", dim(mtcars)[1], " [First 10 rows displayed]")})
#nsamples
output$ncols<- renderText({paste("Number of genes: ", (dim(mtcars)[2]), " [First 10 rows displayed]")})
#display 10rows count matrix
output$matrix <- renderTable({
mtcars
})
}
)
observeEvent(input$reset, {
inputSweetAlert(
session = session, inputId = "mytext", input = "text",
title = "This is a free program, please leave your email:"
)
})
output$text <- renderPrint(input$mytext)
}
)
}
Here is an example using the modal dialog option provided by shiny. I trimmed your example down to the bits that mattered:
library(shiny)
if (interactive()) {
shinyApp(
ui <- fluidPage(
actionButton("reset", "RESET", style="simple", size="sm", color = "warning"),
verbatimTextOutput(outputId = "text")
),
server = function(input, output, session) {
l <- reactiveValues()
observeEvent(input$reset, {
# display a modal dialog with a header, textinput and action buttons
showModal(modalDialog(
tags$h2('Please enter your personal information'),
textInput('name', 'Name'),
textInput('state', 'State'),
footer=tagList(
actionButton('submit', 'Submit'),
modalButton('cancel')
)
))
})
# only store the information if the user clicks submit
observeEvent(input$submit, {
removeModal()
l$name <- input$name
l$state <- input$state
})
# display whatever is listed in l
output$text <- renderPrint({
if (is.null(l$name)) return(NULL)
paste('Name:', l$name, 'and state:', l$state)
})
}
)
}

Loading message for slow downloadhandler()

I would like to ask if there is a way to display a loading message before the file is finally downloaded in my shiny app. My original dataset is big and I guess this is the reason for this delay. Below I attach a toy example in case someone can apply the reuested solution on this.
#ui.r
ui <- fluidPage(
# App title ----
titlePanel("Downloading Data"),
# Sidebar layout with input and output definitions ----
sidebarLayout(
# Sidebar panel for inputs ----
sidebarPanel(
# Input: Choose dataset ----
selectInput("dataset", "Choose a dataset:",
choices = c("rock", "pressure", "cars")),
# Button
downloadButton("downloadData", "Download")
),
# Main panel for displaying outputs ----
mainPanel(
tableOutput("table")
)
)
)
#server.r
server <- function(input, output) {
# Reactive value for selected dataset ----
datasetInput <- reactive({
switch(input$dataset,
"rock" = rock,
"pressure" = pressure,
"cars" = cars)
})
# Table of selected dataset ----
output$table <- renderTable({
datasetInput()
})
# Downloadable csv of selected dataset ----
output$downloadData <- downloadHandler(
filename = function() {
paste(input$dataset, ".csv", sep = "")
},
content = function(file) {
write.csv(datasetInput(), file, row.names = FALSE)
}
)
}
I have implemented a solution based on your code. What you need to do is add a progress bar inside your downloadhandler().
library(shiny)
ui <- fluidPage(
# App title ----
titlePanel("Downloading Data"),
# Sidebar layout with input and output definitions ----
sidebarLayout(
# Sidebar panel for inputs ----
sidebarPanel(
# Input: Choose dataset ----
selectInput("dataset", "Choose a dataset:",
choices = c("rock", "pressure", "cars")),
# Button
downloadButton("downloadData", "Download")
),
# Main panel for displaying outputs ----
mainPanel(
tableOutput("table")
)
)
)
#server.r
server <- function(input, output) {
# Reactive value for selected dataset ----
datasetInput <- reactive({
switch(input$dataset,
"rock" = rock,
"pressure" = pressure,
"cars" = cars)
})
# Table of selected dataset ----
output$table <- renderTable({
datasetInput()
})
# Downloadable csv of selected dataset ----
output$downloadData <- downloadHandler(
filename = function() {
paste(input$dataset, ".csv", sep = "")
},
content = function(file) {
shiny::withProgress(
message = paste0("Downloading", input$dataset, " Data"),
value = 0,
{
shiny::incProgress(1/10)
Sys.sleep(1)
shiny::incProgress(5/10)
write.csv(datasetInput(), file, row.names = FALSE)
}
)
}
)
}
shiny::shinyApp(ui = ui, server = server)
You can tailor this solution to your requirements (customize message, add loop etc). I hope this helps :-)

Update checkboxGroupInput() choices after file upload

I have a simple shiny app below. In this app I want the user to be able to upload his own csv and then automatically this will be added as a choice in the checkbox group below the other dataset "D.B" (which I create in my original app).
#ui.r
ui <- fluidPage(
# App title ----
titlePanel("Uploading Files"),
# Sidebar layout with input and output definitions ----
sidebarLayout(
# Sidebar panel for inputs ----
sidebarPanel(
# Input: Select a file ----
fileInput("file1", "Choose CSV File",
multiple = FALSE,
accept = c("text/csv",
"text/comma-separated-values,text/plain",
".csv")),
uiOutput("checkbox"),
textInput("filename","Set Filename")
),
# Main panel for displaying outputs ----
mainPanel(
# Output: Data file ----
tableOutput("contents")
)
)
)
#server.r
server <- function(input, output) {
output$contents <- renderTable({
req(input$file1)
df <- read.csv(input$file1$datapath)
})
D.B <- reactive({
#some code that creates the dataset D.B.
})
output$checkbox<-renderUI({
checkboxGroupInput("datasetSelector","Specify the datasets to compare:", choices = c("D.B")
)
})
}
You could use a reactive value to store choices then add a choice everytime a file is uploaded. Use an observer to watch for file uploads (I also used the library rlist which gives me the append method).
library(rlist)
#ui.r
ui <- fluidPage(
# App title ----
titlePanel("Uploading Files"),
# Sidebar layout with input and output definitions ----
sidebarLayout(
# Sidebar panel for inputs ----
sidebarPanel(
# Input: Select a file ----
fileInput("file1", "Choose CSV File",
multiple = FALSE,
accept = c("text/csv",
"text/comma-separated-values,text/plain",
".csv")),
uiOutput("checkbox"),
textInput("filename","Set Filename")
),
# Main panel for displaying outputs ----
mainPanel(
# Output: Data file ----
tableOutput("contents")
)
)
)
#server.r
#fileOptions = list("D.B.")
server <- function(input, output, session) {
output$contents <- renderTable({
req(input$file1)
df <- read.csv(input$file1$datapath)
head(df)
})
fileOptions <- reactiveValues(currentOptions=c("D.B."))
observeEvent(input$file1, {
fileOptions$currentOptions = list.append(fileOptions$currentOptions, input$file1$datapath)
})
D.B <- reactive({
#some code that creates the dataset D.B.
})
output$checkbox<-renderUI({
checkboxGroupInput("datasetSelector","Specify the datasets to compare:", choices = fileOptions$currentOptions
)
})
}

Resources