How to create On load Event or default event in shiny?
Asked Answered
B

2

9

I am new to shiny as well as stackoverflow and looking for some help with a problem that I am currently stuck at. I am trying to build a shiny app which collects some inputs from the user and creates visualization based on inputs on click of a button. Currently, that works fine, but one of the major ask is that, when the app loads for the first time, it shall have visualization prepared based on the default inputs.

I am pasting a sample code, which can explain the issue I am facing:

UI.R

  #loading shiny
  library(shiny)
  
  ui<-shinyUI(fluidPage(
    titlePanel("Iris Dataset"),
    sidebarLayout(
      sidebarPanel(
        radioButtons("x", "Select X-axis:",
                     list("Sepal.Length"='a', "Sepal.Width"='b', "Petal.Length"='c', "Petal.Width"='d')),
        radioButtons("y", "Select Y-axis:",
                     list("Sepal.Length"='e', "Sepal.Width"='f', "Petal.Length"='g', "Petal.Width"='h')),
        actionButton("action","Submit")
      ),
      mainPanel(
        plotOutput("distPlot")
      )
    )
  ))
  
  #SERVER.R
  library(shiny)
  
  #loading shiny
  server<-shinyServer(function(input, output) {
    
    observeEvent(input$action,{
    output$distPlot <- renderPlot({if(input$x=='a'){i<-1}
      
      if(input$x=='b'){i<-2}
      
      if(input$x=='c'){i<-3}
      
      if(input$x=='d'){i<-4}
      
      if(input$y=='e'){j<-1}
      
      if(input$y=='f'){j<-2}
      
      if(input$y=='g'){j<-3}
      
      if(input$y=='h'){j<-4}
      
      s    <- iris[, i]
      k    <- iris[, j]
      plot(s,k)
    })
  })
  })
  
  
  shinyApp(ui<-ui, server<-server)

Now if you run this app, you would see that the inputs are selected at the first screen after load (which is as desired) but the visualization appears only after clicking "Submit" button, this is because of the observer event. In the actual app, there are calculation being performed after capturing the inputs at the click of the button. Hence, the calculation triggers only when the actionButton is clicked

Is there a way, we can still keep the "Submit" button and its observe event, but automatically trigger the visualization or the action performed within the observe event at the start i.e. when the app loads for the first time.

Beguine answered 20/2, 2018 at 21:16 Comment(0)
M
11

Using renderPlot or other render functions inside observeEvent is considered bad practice. What you are looking for is a reactive object that represents the plot parameters. You can then access this reactive object inside your renderPlot context. Here is an example

library(shiny)

ui <- shinyUI(fluidPage(
  titlePanel("Iris Dataset"),
  sidebarLayout(
    sidebarPanel(
      radioButtons("x", "Select X-axis:",
                   list("Sepal.Length" = 'a', "Sepal.Width" = 'b',
                        "Petal.Length" = 'c', "Petal.Width" = 'd')),
      radioButtons("y", "Select Y-axis:",
                   list("Sepal.Length" = 'e', "Sepal.Width" = 'f', 
                        "Petal.Length" = 'g', "Petal.Width" = 'h')),
      actionButton("action", "Submit")
    ),
    mainPanel(
      plotOutput("distPlot")
    )
  )
))

server <- shinyServer(function(input, output) {

  user_choice <- eventReactive(input$action,{
    if (input$x == 'a'){i <- 1}    
    if (input$x == 'b'){i <- 2}    
    if (input$x == 'c'){i <- 3}    
    if (input$x == 'd'){i <- 4}    
    if (input$y == 'e'){j <- 1}    
    if (input$y == 'f'){j <- 2}    
    if (input$y == 'g'){j <- 3}    
    if (input$y == 'h'){j <- 4}

    return(c(i, j))

    ## use ignoreNULL to fire the event at startup
  }, ignoreNULL = FALSE)

  output$distPlot <- renderPlot({
    uc <- user_choice()
    plot(iris[, uc[1]], iris[, uc[2]])
  })
})


shinyApp(ui = ui, server = server)

The object user_choice will get updated whenever a user clicks the button or the app starts.

There is also an ignoreNULL parameter in observeEvent but for some reason, that does not yield the same result.

Mellar answered 20/2, 2018 at 22:1 Comment(3)
Sir thanks for your answer. Just to clarify, I am using observe event because, once the inputs are captured, some calculations are performed, which then yields the parameters required for plot. But I understand your point and will try to use the approach and will post the results.Beguine
Why would somebody say that observeEvent is a bad practice? Is simply a particular function with particular results and it is very useful with buttons, for example. These are the kind of answers that confuse new people.Pali
My statment was that using render functions inside observeEvent is bad practice, not that observeEvent should be avoided altogether. You can read up on the newest reference documentation of observeEvent for more details.Mellar
P
0

just set the data for plot in reactiveValues() with a default value corresponding to the default plot during page load... by doing this, the plot shows up during load with the default data, and every time actionbutton is clicked the plot gets updated...

  server<-function(input, output) {

data1 = reactiveValues(plot=default_data)

observeEvent(input$action,{
    data1$plot = new_data
})

renderPlot({
      plot(..., data1$plot)
})

}

Pudens answered 1/8, 2022 at 1:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.