how can a person reset the actionButton back to being selected = character(0) rather than one of the radio buttons that they have available,
any idea?
you can use shinyjs package for this,Thanks to Dean Attali for this wonderful package.
This is an example:
if (interactive()) {
library(shiny)
library(shinyjs)
shinyApp(
ui = fluidPage(
useShinyjs(),
div(
id = "form",
textInput("name", "Name"),
radioButtons("gender", "Gender", c("Male", "Female"))
),
actionButton("resetAll", "Reset all"),
actionButton("resetName", "Reset name"),
actionButton("resetGender", "Reset Gender")
),
server = function(input, output) {
observeEvent(input$resetName, {
reset("name")
})
observeEvent(input$resetGender, {
reset("gender")
})
observeEvent(input$resetAll, {
reset("form")
})
}
)
}
You can read about this in here
To my knowledge it is impossible to reset an actionButton in shiny.
You can consider incrementing a reactiveValue each time the button is clicked, and then checking if this value is odd or even to perform a given action.
Are you trying to use an action button to reset a radio button? Try using updateRadioButton (https://shiny.rstudio.com/reference/shiny/0.14/updateRadioButtons.html). Here is an example:
library("shiny")
ui <- fluidPage(
sidebarPanel(
radioButtons("radio_buttons", "Radio buttons", list("option 1", "option 2"),
selected = character(0)),
actionButton("reset_button", "Reset button")
)
)
server <- function(input, output, session) {
observeEvent(input$reset_button, {
updateRadioButtons(session, "radio_buttons", "Radio buttons", list("option 1", "option 2"),
selected = character(0)
)
})
}
shinyApp(ui = ui, server = server)
Related
In the below example code, I'd like each click of the "Add" button to add 1 to the value presented in the little "data" table underneath. Instead of the "Add" button, the code below has the "Test add" button working this way for demo purpose. I'd like to have "Add" do what "Test add" currently does, and then remove "Test add".
The "Show table" button works as it should: each click renders a larger table (unrelated, this is all a simple example) underneath. And the "Add" button works correctly in hiding the rendered larger table each time it is clicked; but I'd also like a click of "Add" to add 1 as described above.
In the below code I commented out observeEvent("input.show == 'Add'",{x(x()+1)}), which was my attempt to have a click of "Add" cause the addition of 1. How do I correct this, so the observeEvent() is essentially triggered by input.show == 'Add'?
This image helps explain:
Code:
library(shiny)
library(shinyWidgets)
ui <- fluidPage(
br(),actionButton("add","Test add"), br(),br(),
radioGroupButtons(
inputId = "show",
label = NULL,
choices = c("Add","Show table"),
status = "primary",
selected = "Add"
),
br(),
fluidRow(tableOutput("data")),
fluidRow(
conditionalPanel(
"input.show == 'Show table'",
column(10,
column(4, h5(textOutput("text"))),
column(6, tableOutput("table")),
style = "border: 2px solid grey; margin-left: 15px;"
),
style = "display: none;"
)
)
)
server <- function(input, output, session) {
x = reactiveVal(0)
output$data <- renderTable(x())
output$table <- renderTable(iris[1:5, 1:3])
output$text <- renderText("Test show/hide in JS")
observeEvent(input$add,{x(x()+1)})
# observeEvent("input.show == 'Add'",{x(x()+1)})
}
shinyApp(ui, server)
One can easily watch show to create make the value increase by 1 every other time the "add" in show is clicked.
observeEvent(input$show, {
req(input$show == "Add")
x(x()+1)
})
The problem is that you have to click Show table once and then click Add, then the value will increase. If you continuously click Add, the value will only increase one time. To solve the problem, we can bind a new JS event to the Add button and send the value to R.
library(shiny)
library(shinyWidgets)
ui <- fluidPage(
br(), br(), br(), br(),
radioGroupButtons(
inputId = "show",
label = NULL,
choices = c("Add","Show table"),
status = "primary",
selected = "Add"
),
tags$script(HTML(
"
$(()=>{
var clicks = 0;
$('#show button').first().on('click', ()=> {
clicks ++;
Shiny.setInputValue('add_button', clicks);
});
})
"
)),
br(),
fluidRow(tableOutput("data")),
fluidRow(
conditionalPanel(
"input.show == 'Show table'",
column(10,
column(4, h5(textOutput("text"))),
column(6, tableOutput("table")),
style = "border: 2px solid grey; margin-left: 15px;"
),
style = "display: none;"
)
)
)
server <- function(input, output, session) {
x <- reactiveVal(0)
output$data <- renderTable(x())
output$table <- renderTable(iris[1:5, 1:3])
output$text <- renderText("Test show/hide in JS")
observeEvent(input$add_button, {
x(input$add_button)
})
}
shinyApp(ui, server)
Alternative
If this value is only used to display how many times the button is clicked, or if you care about the performance, we can handle this job purely in JS, meaning no server interaction is required. If you have a great number of users, the following will help to decrease your server burden.
library(shiny)
library(shinyWidgets)
ui <- fluidPage(
br(), br(), br(), br(),
radioGroupButtons(
inputId = "show",
label = NULL,
choices = c("Add","Show table"),
status = "primary",
selected = "Add"
),
tags$script(HTML(
"
$(()=>{
var clicks = 0;
$('#show button').first().on('click', ()=> {
clicks ++;
$('#data td').text(` ${clicks} `);
});
})
"
)),
br(),
fluidRow(tableOutput("data")),
fluidRow(
conditionalPanel(
"input.show == 'Show table'",
column(10,
column(4, h5(textOutput("text"))),
column(6, tableOutput("table")),
style = "border: 2px solid grey; margin-left: 15px;"
),
style = "display: none;"
)
)
)
server <- function(input, output, session) {
output$data <- renderTable(0)
output$table <- renderTable(iris[1:5, 1:3])
output$text <- renderText("Test show/hide in JS")
}
shinyApp(ui, server)
I have one selectizeInput and one fileInput in my shiny app.
I want to keep fileInput disabled until some value is not selected in selectizeInput.
Also I want a popup message to select a value every time user clicks on fileInput.
How can I do that.
As others have mentioned, the shinyjs package is useful here. You could use enable, disable, or toggleState.
library(shiny)
library(shinyjs)
ui = fluidPage(
shinyjs::useShinyjs(),
selectizeInput("selector", label="Choose 2:", multiple=TRUE,
choices=letters[1:5], selected=letters[1:5]),
fileInput("file_inputer", label="upload file")#,
# dataTableOutput('table')
)
server = function(input, output) {
observe({
shinyjs::toggleState("file_inputer", length(input$selector) %in% 0:4)
})
observeEvent(input$file_inputer, {
showModal(modalDialog(
title="Do you want a header row?",
selectInput("option_selector", label="Choose an option",
choices=c("option 1", "option 2", "option 3")),
footer = tagList(actionButton("read_file", "Read File"),
modalButton("Cancel")
)
))
})
observeEvent(input$read_file, {
# do something with your option value
removeModal()
})
}
# Run the application
shinyApp(ui = ui, server = server)
I would like to have one of the tabPanels in my Shiny app launch a shinyFiles style input. In this case I would like to launch a shinySaveButton, without the shinySaveButton being in my dataset (By clicking the save icon [which is actually a tabPanel])
Reproducible example below
library(shiny)
library(shinyFiles)
ui <- navbarPage('Test App',id = "inTabset", selected="panel1",
tabPanel(title = "", value = "Save", icon = icon("save")),
tabPanel(title = "Panel 1", value = "panel1",
h1("Panel1")),
tabPanel(title = "Panel 2",value = "panel2",
h1("Panel2"))
)
server <- function(input, output, session) {
values = reactiveValues(tabSelected="panel1")
observe({
if (input$inTabset=="Save") {
updateNavbarPage(session,"inTabset",selected=values$tabSelected)
#CODE FOR LOADING SHINYFILES DIALOG IN HERE
} else {
values$tabSelected<-input$inTabset
}
})
}
shinyApp(ui, server)
Any help would be greatly appreciated.
Work around using hidden element trick
library(shiny)
library(shinyFiles)
library(shinyjs)
jsCode<-"shinyjs.saveButton=function(){ $('#buttonFileSaveHidden').click(); }"
ui <- fluidPage(
useShinyjs(),
extendShinyjs(text = jsCode),
navbarPage('Test App',id = "inTabset", selected="panel1",
tabPanel(title = "", value = "Save", icon = icon("save")),
tabPanel(title = "Panel 1", value = "panel1",
h1("Panel1")
),
tabPanel(title = "Panel 2",value = "panel2",
h1("Panel2"))
),
# HIDDEN BUTTON TO INITIATE THE SAVE
hidden(shinySaveButton( "buttonFileSaveHidden",
label="",
title="Save as ...",
list('hidden_mime_type'=c("R")),
class='hiddenButton')),
wellPanel( #ONLY INCLUDED TO DISPLAY OF PATH INFO OF THE CHOICE
h3('Current save path info'),
tableOutput('table')
)
)
server <- function(input, output, session) {
values = reactiveValues(tabSelected="panel1")
observe({
if (input$inTabset=="Save") {
updateNavbarPage(session,"inTabset",selected=values$tabSelected)
#CODE FOR LOADING SHINYFILES DIALOG IN HERE
js$saveButton()
} else {
values$tabSelected<-input$inTabset
}
})
shinyFileSave(input, "buttonFileSaveHidden", session=session, roots=c(wd="~"), filetypes=c('R') ) #hidden
# GET THE SAVE PATH CHOICE AND RECORD IT IN fp.dt.rv
fp.dt.rv<-reactiveVal("")
observeEvent(input$buttonFileSaveHidden,{
fp.dt<-parseSavePath(c(wd='~'), input$buttonFileSaveHidden)
fp.dt.rv(fp.dt) #or just use to immediately write.
})
# ONLY TO DISPLAY THE SAVE CHOICE
output$table <- renderTable(fp.dt.rv())
}
shinyApp(ui, server)
I am trying to build an app where the user is able to switch tabs when clicking on a specific object. However, I have developed the app using modules and would like to continue to do so. I am running into a problem with the scoping when trying to call the updateNavbarPage() function from inside of the modules. I have created a MWE example to illustrate the problem.
#==================================================
# MRE for updateNavBar scoping issue within modules
#==================================================
modOneUI <- function(id){
ns <- NS(id)
tagList(
h4(
"Click this button to change tabs!"
),
actionButton(
ns("submit"),
label = "Go to next Tab"
)
)
}
modOne <- function(input, output, session){
observeEvent(input$submit, {
updateNavbarPage(session, "nav-page", "tab2")
})
}
ui <- shinyUI(
navbarPage(
id = "nav-page",
title = "Example Navbar Page Issue",
tabPanel(
id = "tab1",
value = "tab1",
div(
"Tab 1"
),
div(
modOneUI("tab1_mod")
)
),
tabPanel(
id = "tab2",
value = "tab2",
div(
"Tab 2"
),
div(
h4("This is the second tab")
)
)
)
)
server <- shinyServer(function(input, output, session){
callModule(modOne, "tab1_mod")
})
shinyApp(ui = ui, server = server)
When this app is run, and the action button is clicked on the first tab, nothing happens. However if you remove the module and place the ui and server module code directly into the ui and server portions then clicking the button works. Here is the code with the modules removed.
ui <- shinyUI(
navbarPage(
id = "nav-page",
title = "Example Navbar Page Issue",
tabPanel(
id = "tab1",
value = "tab1",
div(
"Tab 1"
),
div(
h4(
"Click this button to change tabs!"
),
actionButton(
"submit",
label = "Go to next Tab"
)
)
),
tabPanel(
id = "tab2",
value = "tab2",
div(
"Tab 2"
),
div(
h4("This is the second tab")
)
)
)
)
server <- shinyServer(function(input, output, session){
observeEvent(input$submit, {
updateNavbarPage(session, "nav-page", "tab2")
})
})
shinyApp(ui = ui, server = server)
Is there any way to use updateNavbarPage() from within a module to switch to a tab that is in not in the module?
Do not ask me why :-) but it works like this:
modOne <- function(input, output, session, x){
observeEvent(input$submit, {
updateNavbarPage(x, "nav-page", "tab2")
})
}
callModule(modOne, "tab1_mod", x=session)
I need the user to click a button and be taken to a different tabPanel of a navbarPage. Here is a simple app where this could be implemented. How can I achieve this?
ui <- shinyUI(
navbarPage('Test App',
tabPanel('Page 1',
p('This is the first tab'), br(),
actionButton('jumpToP2', 'Jump to Second Tab')
),
tabPanel('Page 2',
p('This is the second tab'),
actionButton('jumpToP1', 'Jump to First Tab')
)
)
)
server <- shinyServer(function(input, output){
observeEvent(input$jumpToP2,{
## Switch active tab to 'Page 2'
})
observeEvent(input$jumpToP1,{
## Switch active tab to 'Page 1'
})
})
shinyApp(ui, server)
You can use updateTabsetPanel to switch between different tabPanels. See the documentation and example codes at https://shiny.rstudio.com/reference/shiny/latest/updateTabsetPanel.html. The code below should fulfill your requirements.
ui <- navbarPage('Test App',id = "inTabset",
tabPanel(title = "Panel 1", value = "panel1",
actionButton('jumpToP2', 'Jump to Second Tab')),
tabPanel(title = "Panel 2", value = "panel2",
actionButton('jumpToP1', 'Jump to First Tab'))
)
server <- function(input, output, session) {
observeEvent(input$jumpToP2, {
updateTabsetPanel(session, "inTabset",
selected = "panel2")
})
observeEvent(input$jumpToP1, {
updateTabsetPanel(session, "inTabset",
selected = "panel1")
})
}
shinyApp(ui, server)
I'm not so sure that this really the best way for you to design your U... Do you know that tabPanel() will act pretty much the same way as an actionButton() will in this case?
ui <- navbarPage('Test App',id = "inTabset",
tabPanel(title = "Panel 1", uiOutput("panel1")),
tabPanel(title = "Panel 2", uiOutput("panel2"))
)
server <- function(input, output, session) {
output$panel1 <- renderUI({
#your UI data
})
output$panel2 <- renderUI({
#your UI data
})
}
shinyApp(ui, server)