How to clear the mainPanel if a selectInput choice has changed? - r

I am trying to create an app that will show you results depending on a selectInput and the changes are controlled by actionButtons.
When you launch the app, you have to select a choice: Data 1 or Data 2. Once you have selected your choice (e.g. Data 1), you have to click the actionButton "submit type of data". Next, you go to the second tab, choose a column and then click "submit".
The output will be: one table, one text and one plot.
Then, if you go back to the first tab and select "Data 2", everything that you have generated is still there (as it is expected, since you didn't click any button).
However, I would like to remove everything that is in the mainPanel if I change my first selectInput as you could see it when you launch the app for the first time.
The idea is that since you have changed your first choice, you will have to do the same steps again (click everything again).
I would like to preserve and control the updates with actionButtons as I have in my code (since I am working with really long datasets and I don't want to depend on the speed of loading things that I don't want until I click the button). Nevertheless, I cannot think a way to remove everything from mainPanel if I change the choice of the first selectInput.
Does anybody have an idea how I can achieve this?
Thanks in advance
Code:
library(shiny)
library(shinyWidgets)
library(shinyFeedback)
library(DT)
library(datasets)
ui <- fluidPage(
sidebarPanel(
tabsetPanel(id="histogram",
tabPanel("Selection",
useShinyFeedback(),
selectInput(inputId = "type", label = "Select your data",
choices = c("Data 1" = "data1",
"Data 2" = "data2")),
conditionalPanel(
condition = "input.type == 'data2'",
div(style = "position:absolute;right:2.5em;",
actionButton(
inputId = "button_more_info_data2",
label = "More info",
icon = icon("info-circle"))
)
),
actionButton(
inputId = "button",
label = "Submit type of data",
icon = icon("check")
)
),
tabPanel("Pick the column",
br(),
selectizeInput(inputId = "list_columns", label = "Choose the column:", choices=character(0)),
actionButton(
inputId = "button2",
label = "Submit")
))
),
mainPanel(
dataTableOutput("table"),
textOutput("text"),
plotOutput("myplot")
)
)
server <- function(input, output, session) {
observeEvent(input$type,{
feedbackWarning(inputId = "type",
show = ("data2" %in% input$type),
text ="This data is... Please, be careful..."
)
})
mydata <- reactive({
if(input$type == "data1"){
mtcars
}else{
iris
}
}) %>% bindEvent(input$button2)
# This is to generate the choices (gene list) depending on the user's input.
observeEvent(input$button, {
updateSelectizeInput(
session = session,
inputId = "list_columns",
choices = colnames(trees), options=list(maxOptions = length(colnames(trees))),
server = TRUE
)
})
output$table <- renderDataTable({
req(input$button2)
mydata()
})
output$text <- renderText({
req(input$button2)
input$list_columns
})
output$myplot <- renderPlot({
req(input$button2, input$button)
hist(trees[,input$list_columns])
})
}
if (interactive())
shinyApp(ui, server)

Here is an example using a reset button - using the selectInput you'll end up with a circular reference:
library(shiny)
library(shinyWidgets)
library(shinyFeedback)
library(DT)
library(datasets)
ui <- fluidPage(sidebarPanel(tabsetPanel(
id = "histogram",
tabPanel(
"Selection",
useShinyFeedback(),
selectInput(
inputId = "type",
label = "Select your data",
choices = c("Data 1" = "data1",
"Data 2" = "data2")
),
conditionalPanel(
condition = "input.type == 'data2'",
div(
style = "position:absolute;right:2.5em;",
actionButton(
inputId = "button_more_info_data2",
label = "More info",
icon = icon("info-circle")
)
)
),
actionButton(
inputId = "button",
label = "Submit type of data",
icon = icon("check")
),
actionButton(
inputId = "reset",
label = "Reset",
icon = icon("xmark")
)
),
tabPanel(
"Pick the column",
br(),
selectizeInput(
inputId = "list_columns",
label = "Choose the column:",
choices = character(0)
),
actionButton(inputId = "button2",
label = "Submit")
)
)),
mainPanel(
dataTableOutput("table"),
textOutput("text"),
plotOutput("myplot")
))
server <- function(input, output, session) {
observeEvent(input$type, {
feedbackWarning(
inputId = "type",
show = ("data2" %in% input$type),
text = "This data is... Please, be careful..."
)
})
mydata <- reactiveVal(NULL)
observe({
if (input$type == "data1") {
mydata(mtcars)
} else if (input$type == "data2") {
mydata(iris)
} else {
mydata(data.frame())
}
}) %>% bindEvent(input$button2)
observeEvent(input$reset, {
mydata(data.frame())
})
# This is to generate the choices (gene list) depending on the user's input.
observeEvent(input$button, {
updateSelectizeInput(
session = session,
inputId = "list_columns",
choices = colnames(trees),
options = list(maxOptions = length(colnames(trees))),
server = TRUE
)
})
output$table <- renderDataTable({
req(input$button2)
mydata()
})
output$text <- renderText({
req(input$button2)
input$list_columns
})
output$myplot <- renderPlot({
req(input$button2, input$button)
hist(trees[, input$list_columns])
})
}
shinyApp(ui, server)

Related

Change color of slider using updateSliderTextInput

I am trying to change the color of the slide when updating its values. I have tried different ways without success. The following code does not run, but replicates what I am trying to do:
if (interactive()) {
library("shiny")
library("shinyWidgets")
ui <- fluidPage(
br(),
sliderTextInput(
inputId = "mySlider",
label = "Pick a month :",
choices = month.abb,
selected = "Jan"
),
verbatimTextOutput(outputId = "res"),
radioButtons(
inputId = "up",
label = "Update choices:",
choices = c("Abbreviations", "Full names")
)
)
server <- function(input, output, session) {
output$res <- renderPrint(str(input$mySlider))
observeEvent(input$up, {
choices <- switch(
input$up,
"Abbreviations" = month.abb,
"Full names" = month.name
)
updateSliderTextInput(
session = session,
inputId = "mySlider",
choices = choices,
color = "red" # This is the line I need to add
)
}, ignoreInit = TRUE)
}
shinyApp(ui = ui, server = server)
}
Maybe has someone the answer to this?
I was able to give this some more thought and figured out a way to update the slider color based on an input. shinyWidgets::setSliderColor essentially just injects CSS to overwrite all the classes associated with the sliderInputs. So it needs to be included in the UI instead of the server. (Took a min to realize that).
I set up a blank uiOutput which is then updated by observing input$up with the new or default color.
Demo
ui <- fluidPage(
br(),
mainPanel(class = "temp",
uiOutput('s_color'), # uiOuput
sliderTextInput(
inputId = "mySlider",
label = "Pick a month :",
choices = month.abb,
selected = "Jan"
),
verbatimTextOutput(outputId = "res"),
radioButtons(
inputId = "up",
label = "Update choices:",
choices = c("Abbreviations", "Full names")
)
)
)
server <- function(input, output, session) {
output$res <- renderPrint(str(input$mySlider))
# output$s_color = renderUI({})
observeEvent(input$up, {
choices <- switch(
input$up,
"Abbreviations" = month.abb,
"Full names" = month.name
)
updateSliderTextInput(
session = session,
inputId = "mySlider",
choices = choices
)
output$s_color = renderUI({ # add color
if (input$up == "Full names") {
setSliderColor(c("Red"), c(1))
} else {
setSliderColor(c("#428bca"), c(1))
}
})
}, ignoreInit = TRUE)
}
shinyApp(ui = ui, server = server)

How to align to the right an actionButton inside a ConditionalPanel?

I am creating a shiny app where depending on your selectInput, you will see an extra actionButton or not. In order to get that, this extra button has to be inside a conditionalPanel.
I want to have both actionButtons aligned, the regular one on the left and the extra, on the right. Thanks to this post I managed to move it to the right, but they are not aligned as you can see in the attached image.
Code:
library(shiny)
library(shinyWidgets)
library(shinyFeedback)
library(DT)
ui <- fluidPage(
sidebarPanel(
useShinyFeedback(),
selectInput(inputId = "type", label = "Select your data",
choices = c("Data 1" = "data1",
"Data 2" = "data2")),
actionButton(
inputId = "button",
label = "Submit type of data",
icon = icon("check")
),
conditionalPanel(
condition = "input.type == 'data2'",
div(style = "position:absolute;right:1em;",
actionButton(
inputId = "button_more_info_data2",
label = "More info",
icon = icon("info-circle"))
)
)
),
mainPanel(
dataTableOutput("table")
)
)
server <- function(input, output, session) {
observeEvent(input$button, {
if(input$type == "data2"){
show_alert(
title = "Are you sure?",
text = HTML("This data is....<br>Please, be careful with..."),
type = "warning",
html = TRUE
)
}else{
show_alert(
title = "OK",
text = "You don't have to do anything",
type = "success"
)
}
})
observeEvent(input$type,{
feedbackWarning(inputId = "type",
show = ("data2" %in% input$type),
text ="This data is... Please, be careful..."
)
})
mydata <- reactive({
if(input$type == "data1"){
mtcars
}else{
iris
}
}) %>% bindEvent(input$button)
output$table <- renderDataTable(mydata())
}
if (interactive())
shinyApp(ui, server)
I also tried what they answered in:
1- This post, but it doesn't work for me because I am not working with columns.
conditionalPanel(
condition = "input.type == 'data2'",
actionButton(
inputId = "button_more_info_data2",
label = "More info",
icon = icon("info-circle"),
style = 'margin-top:25px'
)
)
2- These two from this post:
conditionalPanel(
condition = "input.type == 'data2'",
div(style="display:inline-block",
actionButton(
inputId = "button_more_info_data2",
label = "More info",
icon = icon("info-circle"),
style="float:right")
)
)
conditionalPanel(
condition = "input.type == 'data2'",
div(style = "display:inline-block; float:right",
actionButton(
inputId = "button_more_info_data2",
label = "More info",
icon = icon("info-circle"))
)
)
3- And this option (but I think it depends on another actionButton and it doesn't work for me).
conditionalPanel(
condition = "input.type == 'data2'",
div(style = "display:inline-block",
actionButton(
inputId = "button_more_info_data2",
label = "More info",
icon = icon("info-circle"))
)
)
Does anybody know how to have both actionButtons aligned?
Thanks in advance
I found the solution by chance.
The order of the conditionalPanel has to be moved before the regular actionButton and instead of writing 1em, it would be 2.5em to have the button and the selectInput justified.
library(shiny)
library(shinyWidgets)
library(shinyFeedback)
library(DT)
ui <- fluidPage(
sidebarPanel(
useShinyFeedback(),
selectInput(inputId = "type", label = "Select your data",
choices = c("Data 1" = "data1",
"Data 2" = "data2")),
conditionalPanel(
condition = "input.type == 'data2'",
div(style = "position:absolute;right:2.5em;",
actionButton(
inputId = "button_more_info_data2",
label = "More info",
icon = icon("info-circle"))
)
),
actionButton(
inputId = "button",
label = "Submit type of data",
icon = icon("check")
),
),
mainPanel(
dataTableOutput("table")
)
)
server <- function(input, output, session) {
observeEvent(input$button, {
if(input$type == "data2"){
show_alert(
title = "Are you sure?",
text = HTML("This data is....<br>Please, be careful with..."),
type = "warning",
html = TRUE
)
}else{
show_alert(
title = "OK",
text = "You don't have to do anything",
type = "success"
)
}
})
observeEvent(input$type,{
feedbackWarning(inputId = "type",
show = ("data2" %in% input$type),
text ="This data is... Please, be careful..."
)
})
mydata <- reactive({
if(input$type == "data1"){
mtcars
}else{
iris
}
}) %>% bindEvent(input$button)
output$table <- renderDataTable(mydata())
}
if (interactive())
shinyApp(ui, server)
shinyApp(ui, server)
Here is an approach using a column() construct:
library(shiny)
library(shinyWidgets)
library(shinyFeedback)
library(DT)
ui <- fluidPage(
useShinyFeedback(),
sidebarPanel(
selectInput(
inputId = "type",
label = "Select your data",
choices = c("Data 1" = "data1",
"Data 2" = "data2")
),
fluidRow(
column(4,
actionButton(
inputId = "button",
label = "Submit type of data",
icon = icon("check"),
width = "100%"
)
),
column(4,
conditionalPanel(
condition = "input.type == 'data2'",
actionButton(
inputId = "button_more_info_data2",
label = "More info",
icon = icon("info-circle"),
width = "100%"
)
),
offset = 4
)
)
),
mainPanel(dataTableOutput("table"))
)
server <- function(input, output, session) {
observeEvent(input$button, {
if (input$type == "data2") {
show_alert(
title = "Are you sure?",
text = HTML("This data is....<br>Please, be careful with..."),
type = "warning",
html = TRUE
)
} else{
show_alert(title = "OK",
text = "You don't have to do anything",
type = "success")
}
})
observeEvent(input$type, {
feedbackWarning(
inputId = "type",
show = ("data2" %in% input$type),
text = "This data is... Please, be careful..."
)
})
mydata <- reactive({
if (input$type == "data1") {
mtcars
} else{
iris
}
}) %>% bindEvent(input$button)
output$table <- renderDataTable(mydata())
}
if (interactive())
shinyApp(ui, server)
And another one using splitLayout:
library(shiny)
library(shinyWidgets)
library(shinyFeedback)
library(DT)
ui <- fluidPage(
useShinyFeedback(),
sidebarPanel(
selectInput(
inputId = "type",
label = "Select your data",
choices = c("Data 1" = "data1",
"Data 2" = "data2")
),
splitLayout(cellWidths = c("45%", "10%", "calc(45% - 8px)"), actionButton(
inputId = "button",
label = "Submit type of data",
icon = icon("check"),
width = "100%"
),
div(),
conditionalPanel(
condition = "input.type == 'data2'",
actionButton(
inputId = "button_more_info_data2",
label = "More info",
icon = icon("info-circle"),
width = "100%"
)
))
),
mainPanel(dataTableOutput("table"))
)
server <- function(input, output, session) {
observeEvent(input$button, {
if (input$type == "data2") {
show_alert(
title = "Are you sure?",
text = HTML("This data is....<br>Please, be careful with..."),
type = "warning",
html = TRUE
)
} else{
show_alert(title = "OK",
text = "You don't have to do anything",
type = "success")
}
})
observeEvent(input$type, {
feedbackWarning(
inputId = "type",
show = ("data2" %in% input$type),
text = "This data is... Please, be careful..."
)
})
mydata <- reactive({
if (input$type == "data1") {
mtcars
} else{
iris
}
}) %>% bindEvent(input$button)
output$table <- renderDataTable(mydata())
}
if (interactive())
shinyApp(ui, server)
You can set the attribute align in column() to either left or right as you wish:
library(shiny)
library(shinyWidgets)
library(shinyFeedback)
library(DT)
ui <- fluidPage(
useShinyFeedback(),
sidebarPanel(
selectInput(
inputId = "type",
label = "Select your data",
choices = c("Data 1" = "data1",
"Data 2" = "data2")
),
fluidRow(
column(
width = 6,
align = "left",
actionButton(
inputId = "button",
label = "Submit type of data",
icon = icon("check"),
width = "100%"
)
),
column(
width = 6,
align = "right",
conditionalPanel(
condition = "input.type == 'data2'",
actionButton(
inputId = "button_more_info_data2",
label = "More info",
icon = icon("info-circle"),
width = "100%"
)
)
)
)
),
mainPanel(dataTableOutput("table"))
)
server <- function(input, output, session) {
observeEvent(input$button, {
if (input$type == "data2") {
show_alert(
title = "Are you sure?",
text = HTML("This data is....<br>Please, be careful with..."),
type = "warning",
html = TRUE
)
} else{
show_alert(title = "OK",
text = "You don't have to do anything",
type = "success")
}
})
observeEvent(input$type, {
feedbackWarning(
inputId = "type",
show = ("data2" %in% input$type),
text = "This data is... Please, be careful..."
)
})
mydata <- reactive({
if (input$type == "data1") {
mtcars
} else{
iris
}
}) %>% bindEvent(input$button)
output$table <- renderDataTable(mydata())
}
if (interactive())
shinyApp(ui, server)

Access sessions for action link in Nested Tabset and Tabpanels in R shiny

Here I'm trying to create a actionlink between tabs, but I have many nested tabs within and since I'm calling the links from the nested tabs itself and not the main session, I'm not able to place the id's correctly.
I've looked into this question : Question , but this works for only the main session.
Here's a part of my reproducible code:
ui <- fluidPage(
navbarPage(id = "Navbar",
tabPanel("About",..
actionLink("link_to_overview", "Let's start with the Overview!"), <--- This works
),
tabPanel("Overview",
tabsetPanel(id = "Tab_ov",
tabPanel("Flights",..
actionLink("link_to_airlines", "Let's go to the Airlines!"),<--- This doesn't work
),
tabPanel("Airlines",..
actionLink("link_to_domestic_stats", "Let's go to the Domestic!") <--- This doesn't work
),
)),
tabPanel("Statistics",
tabsetPanel(id = "stats_tab",
tabPanel("Domestic",..
),
tabPanel("International",..),
))
))
server <- function(input, output, session) {
observeEvent(input$link_to_overview, {
newvalue <- "Overview"
updateTabItems(session, "Navbar", newvalue)
})
observeEvent(input$link_to_airlines, {
updateTabsetPanel(session, inputId = 'Flights', selected = 'Tab_ov')
updateTabsetPanel(session, inputId = 'Overview', selected = 'Airlines')
})
observeEvent(input$link_to_domestic_stats, {
updateTabsetPanel(session, inputId = 'Overview', selected = 'Statistics')
updateTabsetPanel(session, inputId = 'stats_tab', selected = 'Domestic')
})
}
Try this:
library(shiny)
library(tidyverse)
ui <- fluidPage(navbarPage(
id = "Navbar",
tabPanel(
"About",
actionLink("link_to_overview", "Let's start with the Overview!")
),
tabPanel("Overview",
tabsetPanel(
tabPanel(
"Flights",
value = 'flights',
actionLink("link_to_airlines", "Let's go to the Airlines!")
),
tabPanel(
"Airlines",
value = 'airlines',
actionLink("link_to_domestic_stats", "Let's go to the Domestic!")
), id = "Tab_ov"
),value = 'ovview'),
tabPanel(
"Statistics",
tabsetPanel(
tabPanel("Domestic", value = 'domestic'),
tabPanel("International", ''),
id = "stats_tab")
)
))
server <- function(input, output, session) {
observeEvent(input$link_to_overview, {
updateTabsetPanel(session, "Navbar", 'ovview')
})
observeEvent(input$link_to_airlines, {
updateTabsetPanel(session, inputId = 'Tab_ov', selected = 'airlines')
})
observeEvent(input$link_to_domestic_stats, {
updateTabsetPanel(session, inputId = 'Navbar', selected = 'Statistics')
updateTabsetPanel(session, inputId = 'stats_tab', selected = 'domestic')
})
}
shinyApp(ui, server)

R Shiny - How to show/hide "fileinput" based on condition (tab panel selection)

I need to show "fileinput"/file upload option when a particular tabpanel is selected.
Ex. There are 3 tabpanels like A,B and C
When tab B is selected the "fileinput" option should appear and when A or C is selected, the "fileinput" option should be hidden from the sidebarpanel.
I tried the below but not working. Can anyone help? Thanks...
sidebarPanel(
conditionalPanel(condition = "input$id == 'B'", fileInput("file", "Choose xlsx file", accept = ".xlsx"))
mainPanel(
tabsetPanel(
tabPanel("A", value = 'A', DT::dataTableOutput("Table A")),
tabPanel("B", value = 'B', DT::dataTableOutput("Table B")),
tabPanel("C", value = 'C', DT::dataTableOutput("Table C")),
id ="tabselected"
)
)
You need to use the appropriate ID of the tabsetPanel in the condition with a . instead of $. Try this
library(readxl)
runApp(list(
ui = shinyUI(
fluidPage(
sidebarLayout(
sidebarPanel(
conditionalPanel(condition = "input.tabselected == 'tab2'",
fileInput("file", "Choose xlsx file", accept = ".xlsx")),
selectInput(
inputId = 'selected.indicator',
label = 'Select an option: ',
choices = colnames(mtcars)
)
),
mainPanel(
tabsetPanel(
tabPanel("A", value = 'tab1', DTOutput("t1")),
tabPanel("B", value = 'tab2', DTOutput("t2")),
tabPanel("C", value = 'tab3', DTOutput("t3")),
id ="tabselected"
)
)
)
)
),
server = function(input, output, session) {
output$t1 <- renderDT(cars)
output$t3 <- renderDT(mtcars)
mydata <- reactive({
req(input$file)
inFile <- input$file
df <- read_excel(inFile$datapath)
})
output$t2 <- renderDT({
req(mydata())
mydata()
})
}
))

Add items to the list of the selectInput by using button (RShiny)

I have the following code:
library(shiny)
vec <- seq(1,10)
ui <- fluidPage(
titlePanel(""),
sidebarLayout(
sidebarPanel(
fluidRow(
selectInput("selection", "Select number", vec, multiple = TRUE),
actionButton("First_fives", "First Fives" ),
actionButton("Last_fives", "Last Fives"),
actionButton("ok", "OK"))
),
mainPanel(
fluidRow(
h5("Selected numbers:")),
textOutput('num')
)
)
)
server <- function(input, output, session) {
observeEvent(input$First_fives,{
updateSelectInput(session, inputId = "selection", choices = vec[1:5])
})
observeEvent(input$Last_fives,{
updateSelectInput(session, inputId = "selection", choices = vec[6:10])
})
data <- reactiveValues()
observeEvent(input$ok,{
data$selected <- input$city
})
output$num <- renderText({data$selected})
}
shinyApp(ui = ui, server = server)
I almost managed to do what I want but not quite.
My selectInput box is empty when running the code and you can select amongst 10 items (from 1 to 10). This is fine.
Now I would like, when clicking on the button "First fives", the numbers 1 to 5 to be added to this empty box. In others words I would like to get the same as on the picture below in one click.
Please add selected on the updateSelectInput. The code will be like this:
observeEvent(input$First_fives,{
updateSelectInput(session, inputId = "selection", choices = vec[1:5],selected = vec[1:5])
})
observeEvent(input$Last_fives,{
updateSelectInput(session, inputId = "selection", choices = vec[6:10],selected = vec[6:10])
})
Please not I have only checked this function,not others.
Pls check if this meet your requirements.

Resources