Can modal dialog be used with eventReactive?

1,106 views
Skip to first unread message

rdabbler

unread,
Jan 25, 2017, 5:47:12 PM1/25/17
to Shiny - Web Framework for R
Hello,

I wanted to check if it is possible to use modal dialog with eventReactive.

Below is a small example where I am using modal dialog when data is read in (with observeEvent).

library(shiny)

ui = fluidPage(
    actionButton("loaddata","Load Data"),
    verbatimTextOutput("data")
)

server = function(input,output){
    
    rvs = reactiveValues(df = NULL)
    
    observeEvent(input$loaddata,{
        
        # dummy code here - in reality this will be a piece of code that reads/generates some data
        rvs$df = data.frame(x=c(1,2,3),y = c("a","b","c")) 
        
        showModal(modalDialog(
            title = "Important message",
            "Data has been loaded!"
        ))

        })    

    output$data = renderPrint(
        head(rvs$df,20)
    )
}

shinyApp(ui = ui, server = server)


The code for reading in data with eventReactive is below. But in this version, I am not sure where the modal dialog will need to be in the code so that it pops up when data is read.

ui = fluidPage(
    actionButton("loaddata","Load Data"),
    verbatimTextOutput("data")
)

server = function(input,output){
    
    df = eventReactive(input$loaddata,{
        
        # dummy code here - in reality this will be a piece of code that reads/generates some data
        df = data.frame(x=c(1,2,3),y = c("a","b","c")) 
        
        return(df) 
    })    
    
    output$data = renderPrint(
        head(df(),20)
    )
}

shinyApp(ui = ui, server = server)



Thanks,
Shankar

Bárbara Borges

unread,
Jan 25, 2017, 11:36:51 PM1/25/17
to Shiny - Web Framework for R
While you can use showModal inside a call to eventReactive, that is not very good practice. In Shiny, you should aim at doing side effects (like showing a modal) only inside of observers. The best way to include a modal for an app like the one that you have is to actually create a dedicated observer for that (in this case, I chose an observeEvent that runs whenever the values of df() changes):

ui = fluidPage(
  actionButton("loaddata", "Load Data"),
  verbatimTextOutput("data")
)

server = function(input, output, session) {
  # step 1: load the data
  df = eventReactive(input$loaddata,{
    data.frame(x=c(1,2,3),y = c("a","b","c")) 
  })    
  
  # step 2: alert that data has been loaded
  observeEvent(df(),
    showModal(modalDialog(
      title = "Important message",
      "Data has been loaded!"
    ))
  )
  
  # step 3: display the data (occurs at the same time as step 2)
  output$data = renderPrint(
    head(df(), 20)
  )
}

shinyApp(ui = ui, server = server)

While it may seem like too much trouble, I guarantee you that breaking down the steps that your app needs to perform in this way, will make it a lot more scalable in the future. In addition, it's pretty nice when each chunk of code does one thing only (makes it easier to debug!) If you were doing both the loading and the alerting in the same function, it may be harder to understand where problems are coming from.

Most importantly, this is the recommended way of doing things in Shiny and it doesn't add any computational cost.

Hope this helped!

rdabbler

unread,
Jan 26, 2017, 3:11:47 PM1/26/17
to Shiny - Web Framework for R

Barbara,

Thanks for your time to answer my question. You suggestions are very helpful.

Shankar

Reply all
Reply to author
Forward
0 new messages