R Shiny: refreshing/overriding actionButton() output - r

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)

Related

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)
})
}

How to display default plot in www/ before actionButton is clicked R shiny

Here is a sample code to generate a plot upon clicking the actionButton.
shinyApp(
shinyUI(fluidPage(
inputPanel(
numericInput("n", "n", 10),
actionButton("update", "Update")
),
plotOutput("plot")
)),
shinyServer(function(input, output) {
values <- reactiveValues()
values$data <- c()
obs <- observe({
input$update
isolate({ values$data <- c(values$data, runif(as.numeric(input$n), -10, 10)) })
}, suspended=TRUE)
obs2 <- observe({
if (input$update > 0) obs$resume()
})
output$plot <- renderPlot({
dat <- values$data
hist(dat)
})
})
)
I would like to display a default plot which is in www/test.png to appear when the application is launched. And then change the plot after clicking the actionButton as per the user input.
First, I create a simple plot, export it as an image (manually, not in code) and name it Rplot.png (save it where you want):
plot(mtcars$mpg)
Then, in the shiny app, we have to distinguish two situations :
when the app starts, no button is clicked yet, we render the image with renderImage
when we click on the button, we replace renderImage with renderPlot and render an interactive plot
This means that we must use uiOutput in ui part so that we can choose the output to be an image or a plot according to the situation.
Here's an example (I didn't adapt your code but it should not be too difficult):
library(shiny)
# determine your path to image here (you should use the package "here" to do so)
ui <- fluidPage(
selectInput("choice", "Choose", choices = names(mtcars)),
actionButton("run", "Run"),
uiOutput("some_ui")
)
server <- function(input, output, session) {
### "Static" part: no click on actionButton yet
output$some_ui <- renderUI({
imageOutput("image_plot")
})
output$image_plot <- renderImage({
list(src = "Rplot.png",
contentType = 'image/png')
}, deleteFile = FALSE) # Do not forget this option
### Click on actionButton
observeEvent(input$run, {
output$some_ui <- renderUI({
plotOutput("dynamic_plot")
})
output$dynamic_plot <- renderPlot({
plot(mtcars[[input$choice]])
})
})
}
shinyApp(ui, server)
The key is to use renderUI, so you can either show an image or a R plot. This should do what you desire:
shinyApp(
shinyUI(fluidPage(
inputPanel(
numericInput("n", "n", 10),
actionButton("update", "Update")
),
uiOutput("out")
)),
shinyServer(function(session, input, output) {
values <- reactiveValues()
# check if plot has been already rendered
check <- reactiveVal(FALSE)
values$data <- c()
observeEvent(input$update, {
# set check to TRUE
check(TRUE)
input$update
values$data <- c(values$data, runif(as.numeric(input$n), -10, 10))
dat <- values$data
output$plot <- renderPlot({
hist(dat)
})
})
# initial picture.
output$picture <- renderImage({
list(src = "temp.png")
}, deleteFile = FALSE)
output$out <- renderUI({
# in the beginning, check is FALSE and the picture is shown
if (!check()) {
imageOutput("picture")
} else {
# as soon as the button has been pressed the first time,
# the plot is shown
plotOutput("plot")
}
})
})
)
I know, that this has been solved a while, but I needed a solution, without uiOutput. Plus I find this much simpler.
library(shiny)
if (interactive()) {
shinyApp(
ui = fluidPage(
actionButton("btn", "Click me"),
br(),
plotOutput('some_plot', width = '100%')
),
server = function(input, output) {
output$some_plot <- renderPlot({
if (!input$btn) {
# default plot
plot(1, 1, col = 'red')
} else{
# updated plot
plot(1000, 1000, col = 'green')
}
})
}
)
}

Shiny - observeEvent appears without click

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)

Update a variable with input data

I'm trying to append a value taken from an input (in the present case input$n) to a list (in the present case the variable "keyword_list"), when the user presses the an action button (in the present case the button input$goButton).
ui.R
library(shiny)
pageWithSidebar(
headerPanel("actionButton test"),
sidebarPanel(
#numericInput("n", "N:", min = 0, max = 100, value = 50),
textInput("n", "Caption", "Enter next keyword"),
br(),
actionButton("goButton", "Go!"),
p("Click the button to update the value displayed in the main panel.")
),
mainPanel(
verbatimTextOutput("nText"),
dataTableOutput('mytable')
)
)
})
server.R
library(shiny)
# Define server logic required to summarize and view the selected
# dataset
function(input, output,session) {
#prepare data
keyword_list <- matrix()
makeReactiveBinding('keyword_list')
observe({
if (input$goButton == 0)
return()
isolate({
keyword_list <- append(keyword_list,input$n) })
})
ntext <- eventReactive(input$goButton, {
input$n
})
output$nText <- renderPrint({
#input$n
ntext()
})
output$mytable = renderDataTable({
as.data.frame(keyword_list)
})
}
How about this:
library(shiny)
ui <- pageWithSidebar(
headerPanel("actionButton test"),
sidebarPanel(
#numericInput("n", "N:", min = 0, max = 100, value = 50),
textInput("n", "Caption", "Enter next keyword"),
br(),
actionButton("goButton", "Go!"),
p("Click the button to update the value displayed in the main panel.")
),
mainPanel(
verbatimTextOutput("nText"),
dataTableOutput('mytable')
)
)
})
library(shiny)
# Define server logic required to summarize and view the selected
# dataset
server <- function(input, output,session) {
global <- reactiveValues(keyword_list = "")
observe({
if (input$goButton == 0)
return()
isolate({
global$keyword_list <- append(global$keyword_list, input$n)
})
})
ntext <- eventReactive(input$goButton, {
input$n
})
output$nText <- renderPrint({
#input$n
ntext()
})
output$mytable = renderDataTable({
as.data.frame(global$keyword_list)
})
}
shinyApp(ui, server)

Shiny: How to make reactive value initialize with default value

Consider the following actionButton demo:
http://shiny.rstudio.com/gallery/actionbutton-demo.html
server.R:
shinyServer(function(input, output) {
# 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()
})
})
ui.R:
shinyUI(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.")
),
mainPanel(
verbatimTextOutput("nText")
)
))
In this example, prior to the action button being pressed, the right-hand side panel is empty. I would instead like the text with default value "50" to be rendered by default.
How to I get the output to display with default inputs if the action button has not yet been pressed?
eventReactive also takes ignoreNULL as documented here, which lets you initialise the object without an if statement.
By adding the ,ignoreNULL = FALSE to the original post (give or take some formatting), verbatimTextOutput shows 50 on startup.
This makes for a bit of economy on the server side I guess.
ui <- fluidPage(titlePanel("actionButton test"),
sidebarLayout(
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.")
),
mainPanel(verbatimTextOutput("nText"))
))
server <- function(input, output) {
ntext <- eventReactive(input$goButton, {
input$n
}
# Adding this parameter to the original example makes it work as intended
# with 50 in the output field to begin with
, ignoreNULL = FALSE
)
output$nText <- renderText({
ntext()
})
}
shinyApp(ui = ui, server = server)
shinyServer(function(input, output) {
values <- reactiveValues(default = 0)
observeEvent(input$goButton,{
values$default <- input$goButton
})
# 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({
if(values$default == 0){
50
}
else{
ntext()
}
})
})

Resources