Search code examples
rshinyshinyjsaction-button

Shiny Action button not triggering observeEvent


I'm trying to create a simple shiny app that asks two questions in a sequence. I created a div for each question, with the second one hidden. I am trying to use observeEvent with an action button to trigger a hide for the first div and a show for the second div upon click. However, clicking on the action button is not triggering the observeEvent. Any thoughts on where I'm missing something?

My ui.R is:

library(shiny)
library(shinyjs)


shinyUI(fluidPage(useShinyjs(),

  # Application title
  titlePanel("My Survey App"),

  # Sidebar with a slider input for number of bins
  sidebarLayout(
    sidebarPanel(

    ),

    # Show a plot of the generated distribution
    mainPanel(
      h2("survey"),
      wellPanel(
          h6('Placeholder for Placeholder for question'),
          br(),
          div(id = 'questionseq1div',
              h5('Text Question Here',align = 'center'),
              br(),br(),
              textInput('sequence-question-1', '', value = "", width = '100%', 
                        placeholder = 'Give a detailed explanation of your position on the question.'),
              br(),br(),
              fluidRow(
                column(6, align="center", offset = 3,
                       actionButton(inputId = 'completedquestion1',label = 'Next '),
                       tags$style(type='text/css', "#button { vertical-align: middle; height: 50px; width: 100%; font-size: 30px;}")
                )
              )
          ),
          shinyjs::hidden(div(id = 'questionseq2div',
                              h5('Slider Input Question Here',align = 'center'),
                              br(),br(),
                              sliderInput('sequence-question-2','Min: 1  Max: 5',min = 1,max = 5,step = 1,ticks = T,value = 3),
                              br(),br(),
                              fluidRow(
                                column(6, align="center", offset = 3,
                                       submitButton('completed-question-2','Submit '),
                                       tags$style(type='text/css', "#button { vertical-align: middle; height: 50px; width: 100%; font-size: 30px;}")
                                )
                              )
          )))
    )
  )
))

And my server.R is:

library(shiny)
library(shinyjs)

shinyServer(function(input, output,session) {

  observeEvent(input$completedquestion1,{
    print('Triggered')
    shinyjs::show('questionseq2div')
    shinyjs::hide('questionseq1div')

  })

})

Solution

  • I had to re-structure things to get it to work - I didn't see how you could get it to toggle back and forth without a question list to iterate though. And once that was there, then I added a few obvious things because it was kind of fun...

    Anywhere here is a basic structure to do what you want.

    library(shiny)
    library(shinyjs)
    
    
    qlist <- list(
    "q1" = list(type="qtext","text"="first text question"), 
    "q2" = list(type="qslid","text"="first slider question"), 
    "q3" = list(type="qslid","text"="second slider question"), 
    "q4" = list(type="qtext","text"="second text question")
    )
    u <- shinyUI(fluidPage(useShinyjs(),
    
      # Application title
      titlePanel("My Survey App"),
    
      sidebarLayout(
        sidebarPanel(  ),
    
        mainPanel(
           h2("survey"),
           wellPanel( h6(textOutput("curstatus")), 
                      br(),
                      h4(textOutput("curquestion")), 
           div(id = 'questionseq1div',
               h5('div1 - Text Div',align = 'center'), 
               br(),br(),
               textInput('sequence-question-1', '', value = "", width = '100%', 
                         placeholder = 'Give a detailed explanation of your position on the question.'), 
                br(),br()
            ),
            div(id = 'questionseq2div',
                   h5('div2 - Slider Div',align = 'center'),
                   br(),br(),
                   sliderInput('sequence-question-2','Min: 1  Max: 5',min = 1,max = 5,step = 1,ticks = T,value = 3),
                   br(),br()
             )
            ),
            div(id='nextbuttondiv',fluidRow(
              column(6, align="center", offset = 3,
                     actionButton(inputId = 'completedquestion',label = 'Next '),
                     tags$style(type='text/css', "#button { vertical-align: middle; height: 50px; width: 100%; font-size: 30px;}")
                )
               )
            )
    
    ))))
    s <- shinyServer(function(input, output,session) {
    
           rv <- reactiveValues(qlist=qlist,curqnum=1,inited=FALSE,finished=FALSE)
    
           setupForCurQuestion <- function(){
             qcur <- rv$qlist[[rv$curqnum]]
    
             if (qcur$type=="qtext"){
               shinyjs::show('questionseq1div')
               shinyjs::hide('questionseq2div')
             } else {
               shinyjs::hide('questionseq1div')
               shinyjs::show('questionseq2div')
             }
           }
    
           advanceQuestionAndCheckFinish <- function(){
             if (rv$curqnum==length(rv$qlist)) return(TRUE)
             rv$curqnum <- rv$curqnum+1
             print(rv$curqnum)
             setupForCurQuestion()
             return(FALSE)
           }
    
           isolate(setupForCurQuestion()) 
    
           observeEvent(input$completedquestion,{
             if (!rv$finished){
               rv$finished <- advanceQuestionAndCheckFinish()
               if (rv$finished){
                 shinyjs::hide('nextbuttondiv')
               }
             }
          })
          output$curquestion <- renderText({
            qcur <- rv$qlist[[rv$curqnum]]
            qcur$text
          })
          output$curstatus <- renderText({
            if (rv$finished) return("Finished")
            sprintf("Question %d of %d",rv$curqnum,length(rv$qlist))
          })
    })
    shinyApp(u,s)
    

    Here is a screen shot: enter image description here