Shiny - observeEvent appears without click - r

I would like to develop an application with two buttons :
1. Calculate
2. Refresh
When I click on the button "Calculate", a second button appears. When I click on the second button, a sentence appears : "Le resultat est...". The button refresh clean the web page. Now the page is clean and only the two initial buttons appears : Calculate and Refresh.
If i click another time on the button Calculate, the sentence "Le resultat est..." appears without click on the second button.
Question : How can i do obtain the sentence "Le resultat est..." only after a click on the second button ?
Below my code :
library(shiny)
data_Modele <- deval_Shiny
ui <- fluidPage(
actionButton("runif", "Uniform"),
actionButton("reset", "Clear"),
uiOutput("plot")
)
server <- function(input, output){
v <- reactiveValues(data = NULL)
observeEvent(input$runif, {
v$data <- round(runif(1, min=1, max=nrow(deval_Shiny)),digits = 0)
output$Button<- renderUI({
actionButton("button", "click me")
})
})
observeEvent(input$reset, {
v$data <- NULL
})
observeEvent(input$button, {
output$Reponse <- renderText(paste0("Le resultat est :",v$data))
})
output$plot <- renderUI({
if (is.null(v$data)) return()
tagList(
uiOutput("Button"),
uiOutput("Reponse")
)
})
}
shinyApp(ui, server)
Thank you in advance for your help :)
J.

If you want your uiOutputs to behave separately, I would suggest not to bind them together inside output$plot. So if you don't need them to be together, I would add a variable show_response to control whether you want to display the response or not.
library(shiny)
ui <- fluidPage(
actionButton("runif", "Uniform"),
actionButton("reset", "Clear"),
uiOutput("Button"),
uiOutput("Reponse")
)
server <- function(input, output){
v <- reactiveValues(data = NULL)
show_response <- reactiveValues(state = FALSE)
observeEvent(input$runif, {
v$data <- round(runif(1, min = 1, max = 100), digits = 0)
})
observeEvent(input$reset, {
v$data <- NULL
show_response$state <- FALSE
})
observeEvent(input$button, {
show_response$state <- TRUE
})
output$Button <- renderUI({
req(v$data)
actionButton("button", "click me")
})
output$Reponse <- renderText({
req(show_response$state)
paste0("Le resultat est :", v$data)
})
}
shinyApp(ui, server)

You can use shinyjs and its show and hide functions:
library(shiny)
library(shinyjs)
deval_Shiny <- mtcars
data_Modele <- deval_Shiny
ui <- fluidPage(
useShinyjs(),
actionButton("runif", "Uniform"),
actionButton("reset", "Clear"),br(),
actionButton("button", "click me"),
textOutput("Reponse")
)
server <- function(input, output){
observe({
hide("button")
hide("Reponse")
})
v <- reactiveValues(data = NULL)
observeEvent(input$runif,{
show("button")
v$data <- round(runif(1, min=1, max=nrow(deval_Shiny)),digits = 0)
})
observeEvent(input$reset, {
hide("button")
hide("Reponse")
})
output$Reponse <- renderText(paste0("Le resultat est :",v$data))
observeEvent(input$button, {
show("Reponse")
})
}
shinyApp(ui, server)

Related

Shiny: Update a reactive value with textInput() in modalDialog()

I Want to update a Value based on a textInput() within an modalDialog(). I found this answer which does work, but it uses reactiveValues() which creates problems in my case further down in my code.
Is there a way to to update my value text through textInput() and modalDialog() without the use of reactiveValues()?
This works
library(shiny)
library(shinyWidgets)
if (interactive()) {
shinyApp(
ui <- fluidPage(
actionBttn("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)
})
}
)
}
This does not work
It fails to update the value l when I dont use the l <- reactiveValues().
library(shiny)
library(shinyWidgets)
if (interactive()) {
shinyApp(
ui <- fluidPage(
actionBttn("reset", "RESET", style="simple", size="sm", color = "warning"),
verbatimTextOutput(outputId = "text")
),
server = function(input, output, session) {
l <- NULL
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'),
footer=tagList(
actionButton('submit', 'Submit'),
modalButton('cancel')
)
))
})
# only store the information if the user clicks submit
observeEvent(input$submit, {
removeModal()
l <- input$name
})
# display whatever is listed in l
output$text <- renderPrint({
if (is.null(l)) return(NULL)
paste('Name:', l)
})
}
)
}
renderPrint needs a reactive dependency to be invalidated and re-rendered. Accordingly using a non-reactive variable in this scenario isn't making any sense.
You should rather work on the downstream problems.
Here is another approach using eventReactive:
library(shiny)
library(shinyWidgets)
ui <- fluidPage(
br(),
actionBttn("reset", "RESET", style="simple", size="sm", color = "warning"),
verbatimTextOutput(outputId = "text")
)
server <- function(input, output, session) {
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'),
footer=tagList(
actionButton('submit', 'Submit'),
modalButton('cancel')
)
))
})
# only store the information if the user clicks submit
submittedName <- eventReactive(input$submit, {
removeModal()
input$name
})
output$text <- renderPrint({
req(submittedName())
paste('Name:', submittedName())
})
}
shinyApp(ui, server)
Edit: using reactiveVal for the placeholder:
library(shiny)
library(shinyWidgets)
ui <- fluidPage(
br(),
actionBttn("reset", "RESET", style="simple", size="sm", color = "warning"),
verbatimTextOutput(outputId = "text")
)
server <- function(input, output, session) {
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'),
footer=tagList(
actionButton('submit', 'Submit'),
modalButton('cancel')
)
))
})
submittedName <- reactiveVal("placeholder")
# only store the information if the user clicks submit
observeEvent(input$submit, {
removeModal()
submittedName(input$name)
})
output$text <- renderPrint({
paste('Name:', submittedName())
})
}
shinyApp(ui, server)

How to to update data by clicking actionButton in R in runtime

I want to update output data on update button every time.
Here is my code which show the output on update button for the first time I run the code but in runtime if the input is changed, the output is updated automatically.
library(shiny)
ui <- fluidPage(
titlePanel("My Shop App"),
sidebarLayout(
sidebarPanel(
helpText("Controls for my app"),
selectInput("item",
label = "Choose an item",
choices = list("Keyboard",
"Mouse",
"USB",
sliderInput("price",
label = "Set Price:",
min=0, max = 100, value=10),
actionButton ("update","Update Price")
),
mainPanel(
helpText("Selected Item:"),
verbatimTextOutput("item"),
helpText("Price"),
verbatimTextOutput("price")
)
)
)
server <- function(input, output) {
SelectInput <- eventReactive (input$update , {
output$item = renderText(input$item)
output$price = renderText(input$price)
})
output$item <- renderText(SelectInput())
output$price <- renderText(SelectInput())
}
shinyApp(ui = ui, server = server)
Either create a dependency and put them into the reactive and return it:
server <- function(input, output) {
SelectInput <- eventReactive(input$update,{
list(item = input$item, price = input$price)
})
output$item <- renderText(SelectInput()$item)
output$price <- renderText(SelectInput()$price)
}
Or you can isolate, but then you have to add the button reaction to each listener
server <- function(input, output) {
output$item <- renderText({
req(input$update)
input$update
isolate(input$item)
})
output$price <- renderText({
req(input$update)
input$update
isolate(input$price)
})
}

Understanding why action buttons in Shiny don't work, when using several of them

Why when I put together several action button codes from Shiny manual (https://shiny.rstudio.com/articles/action-buttons.html), it DOES NOT run (i.e. no button reacts) ? Each code separately runs fine. How to fix it?
(This is relates to this post: Convert Shiny App R code to Rmarkdown Shiny App code: with observeEvent and eventReactive)
# Code from https://shiny.rstudio.com/articles/action-buttons.html
library(shiny)
ui <- fluidPage(
# Pattern 1 - Command
tags$head(tags$script(src = "message-handler.js")),
actionButton("do", "Click Me"),
hr(),
# Pattern 2 - Delay reactions
actionButton("go", "Go"),
numericInput("n", "n", 50),
plotOutput("plot2"),
hr(),
# Pattern 4 - Reset buttons
actionButton("runif", "Uniform"),
actionButton("reset", "Clear"),
plotOutput("plot4")
)
server <- function(input, output, session) {
# Pattern 1 - Command
observeEvent(input$do, {
session$sendCustomMessage(type = 'testmessage',
message = 'Thank you for clicking')
})
# Pattern 2 - Delay reactions
randomVals <- eventReactive(input$go, {
runif(input$n)
})
output$plot2 <- renderPlot({
hist(randomVals())
})
# Pattern 4 - Reset buttons
v <- reactiveValues(data = NULL)
observeEvent(input$runif, {
v$data <- runif(100)
})
observeEvent(input$reset, {
v$data <- NULL
})
output$plot4 <- renderPlot({
if (is.null(v$data)) return()
hist(v$data)
})
}
shinyApp(ui, server)
UPDATE:
In the original question I had output$plot in patterns 2 and 4 examples. Now these have been replaced to output$plot2 and output$plot4 - This partially resolved the problem. - Buttons for patterns 2 and 4 work now. However, Pattern 1 is still NOT working.
As suggested you cannot have two outputs with same ID. Try this
library(shiny)
ui <- fluidPage(
# Pattern 1 - Command
#tags$head(tags$script(src = "message-handler.js")),
actionButton("do", "Click Me"),
hr(),
# Pattern 2 - Delay reactions
actionButton("go", "Go"),
numericInput("n", "n", 50),
#plotOutput("plot"),
#hr(),
# Pattern 4 - Reset buttons
actionButton("runif", "Uniform"),
actionButton("reset", "Clear"),
plotOutput("plot")
)
server <- function(input, output, session) {
# Pattern 1 - Command
observeEvent(input$do, {
# session$sendCustomMessage(type = 'testmessage',
# message = 'Thank you for clicking')
print('Thank you for clicking')
})
### Pattern 2 - Delay reactions
randomVals <- eventReactive(input$go, {
runif(input$n)
})
### Pattern 4 - Reset buttons
v <- reactiveValues(data = NULL)
observeEvent(input$runif, {
v$data <- runif(100)
})
observeEvent(input$go, {
v$data <- runif(input$n)
})
observeEvent(input$reset, {
v$data <- NULL
})
output$plot <- renderPlot({
if (is.null(v$data)) {
return()
}else {
hist(v$data)
}
})
}
shinyApp(ui, server)

R Shiny: Cylce the class of an actionButton on click

I'd like to have an actionButton that cycles its class between "btn-success", "btn-warning", "btn-danger" based on the button click. Unfortunately I can't seem to figure out how to get that value into the class argument of the actionButton.
library(shiny)
v <- reactiveValues(btn_status = "btn-secondary")
ui <- fluidPage(
# Application title
titlePanel("Change Button Color on click"),
# Create an action button that cycles through 3 bootstrap colors and can be reset
mainPanel(
actionButton("run","L", class = isolate(v$btn_status)),
actionButton("reset", "Clear"),
textOutput("status"),
)
)
server <- function(input, output) {
observeEvent(input$run, {
v$btn_status <- "btn-success"
})
observeEvent(input$reset, {
v$btn_status <- "NULL"
})
output$status <- renderText({
v$btn_status
})
}
shinyApp(ui = ui, server = server)
It's not entirely clear to me what you're trying to do (see my comment above); but I think you're after something like this:
library(shiny)
valid_status <- c("btn-success", "btn-warning", "btn-danger")
ui <- fluidPage(
titlePanel("Change Button Color on click"),
mainPanel(
uiOutput("statusButton"),
actionButton("reset", "Clear"),
textOutput("status"),
)
)
server <- function(input, output, session) {
v <- reactiveValues(button_idx = 1)
get_button_idx <- reactive(v$button_idx)
output$statusButton <- renderUI({
idx <- get_button_idx()
actionButton("run", "L", class = valid_status[idx])
})
observeEvent(input$run, {
v$button_idx <- ifelse(v$button_idx < 3, v$button_idx + 1, 1)
})
observeEvent(input$reset, {
v$button_idx <- 1
})
output$status <- renderText({
valid_status[v$button_idx]
})
}
shinyApp(ui = ui, server = server)
producing
The key is to use a reactive value within renderUI to update the class of the actionButton. To align the buttons you could use fluidRow if necessary.

R Shiny: refreshing/overriding actionButton() output

I am trying to adapt R Shiny: automatically refreshing a main panel without using a refresh button to a new minimal working example:
ui <- fluidPage(
pageWithSidebar(
headerPanel("actionButton test"),
sidebarPanel(
numericInput("n", "N:", min = 0, max = 100, value = 50),
br(),
actionButton("goButton", "Go!"),
p("Click the button to update the value displayed in the main panel."),
actionButton("newButton", "New Button"),
actionButton("newButton2", "Another New Button")
),
mainPanel(
verbatimTextOutput("nText"),
textOutput("some_text_description"),
plotOutput("some_plot")
)
)
)
server <- function(input, output, session) {
# builds a reactive expression that only invalidates
# when the value of input$goButton becomes out of date
# (i.e., when the button is pressed)
ntext <- eventReactive(input$goButton, {
input$n
})
output$nText <- renderText({
ntext()
})
# Prep some text for output
output$some_text_description <- renderText({
if (input$newButton == 0) {return(NULL)}
else {
"Lorem ipsum dolorom."
}
})
# Prep some figure for output
# Simple Bar Plot
output$some_plot <- renderPlot({
if (input$newButton2 == 0) {return(NULL)}
else {
counts <- table(mtcars$gear)
barplot(counts, main="Car Distribution", xlab="Number of Gears")
}
})
}
shinyApp(ui = ui, server = server)
In the code above, I have three actionButton commands, one which produces a plot, one which produces text output, and one which produces a number (as verbatim text output). As you click through each button, new output appears alongside previously generated output (from the last button you pressed).
Without needing to implement a refresh button that clears everything manually, how do I get each actionButton to override (i.e., wipe) the output of the others automatically without them all stacking atop of each other in the main panel. My understanding is that I need to use some combination of observeEvent, NULL, and reactiveValues but my attempts have so far been unsuccessful.
You can use renderUI() for that.
output$all <- renderUI({
global$out
})
Within a global reactiveValue global$out you can store which ui element you would like to display. (Initially it should be empty, therefore NULL).
global <- reactiveValues(out = NULL)
And then listen for the clicks in the Buttons and update global$out accordingly.
observeEvent(input$goButton, {
global$out <- verbatimTextOutput("nText")
})
observeEvent(input$newButton, {
global$out <- textOutput("some_text_description")
})
observeEvent(input$newButton2, {
global$out <- plotOutput("some_plot")
})
Full app would read:
library(shiny)
ui <- fluidPage(
pageWithSidebar(
headerPanel("actionButton test"),
sidebarPanel(
numericInput("n", "N:", min = 0, max = 100, value = 50),
br(),
actionButton("goButton", "Go!"),
p("Click the button to update the value displayed in the main panel."),
actionButton("newButton", "New Button"),
actionButton("newButton2", "Another New Button")
),
mainPanel(
uiOutput("all")
)
)
)
server <- function(input, output, session) {
global <- reactiveValues(out = NULL)
observeEvent(input$goButton, {
global$out <- verbatimTextOutput("nText")
})
observeEvent(input$newButton, {
global$out <- textOutput("some_text_description")
})
observeEvent(input$newButton2, {
global$out <- plotOutput("some_plot")
})
output$all <- renderUI({
global$out
})
output$nText <- renderText({
input$n
})
output$some_text_description <- renderText({
"Lorem ipsum dolorom."
})
# Simple Bar Plot
output$some_plot <- renderPlot({
counts <- table(mtcars$gear)
barplot(counts, main="Car Distribution", xlab="Number of Gears")
})
}
shinyApp(ui = ui, server = server)

Resources