Search code examples
rtextshinytabspasswords

How to get new text input after entering a password in a tab?


I'm trying to make a R shiny application where people need to answer a riddle (raadsel). When they get the correct answer a popup appears that they have the correct answer and in the main panel a sentence with congratulations, fill the password in the second tab: jouwwachtwoord. That password they have to enter in the second tab in order to get a new textinput where they have to fill their name in. The first part works, but when I go to the second tab and I fill in the password, nothing happens. Underneath I have my code, but I don't see where it goes wrong.

library(shiny)

# Definieer raadsels en antwoorden
raadsels <- c("Ik ben groot als ik jong ben, maar klein als ik oud ben. Wat ben ik?", 
              "Ik ben altijd om je heen, maar nooit gezien. Wat ben ik?")
antwoorden <- c("een boom", "lucht")

# UI voor de spiegel
ui <- fluidPage(
  titlePanel("Interactieve Spiegel"),
  tabsetPanel(
    tabPanel("Raadsel",
             sidebarLayout(
               sidebarPanel(
                 textInput("antwoord", "Wat is je antwoord?"),
                 actionButton("controleer", "Controleer Antwoord")
               ),
               mainPanel(
                 verbatimTextOutput("raadsel_output"),
                 verbatimTextOutput("feedback")
               )
             )
    ),
    tabPanel("Naam en Document",
             sidebarLayout(
               sidebarPanel(
                 conditionalPanel(
                   condition = "!input.wachtwoord_ingevuld",
                   passwordInput("wachtwoord", "Voer het wachtwoord in:"),
                   actionButton("ontgrendel", "Ontgrendel")
                 ),
                 conditionalPanel(
                   condition = "input.wachtwoord_ingevuld",
                   textInput("naam", "Vul je naam in:"),
                   actionButton("bevestig_naam", "Bevestig Naam"),
                   downloadButton("download_doc", "Open Document")
                 )
               ),
               mainPanel(
                 verbatimTextOutput("document_output")
               )
             )
    )
  )
)

# Server logica
server <- function(input, output, session) {
  
  wachtwoord_ingevuld <- reactiveVal(FALSE)
  correct_antwoord_gegeven <- reactiveVal(FALSE)
  
  output$raadsel_output <- renderText({
    raadsels[1]  # Weergeef het eerste raadsel
  })
  
  output$feedback <- renderText({
    if (correct_antwoord_gegeven()) {
      "Gefeliciteerd! Voer het wachtwoord in om verder te gaan."
    } else {
      ""
    }
  })
  
  observeEvent(input$controleer, {
    antwoord <- tolower(input$antwoord)  # Antwoorden zijn niet hoofdlettergevoelig
    
    if (antwoord %in% tolower(antwoorden)) {
      showModal(
        modalDialog(
          title = "Goed Geraden!",
          "Jullie mogen de envelop openen."
        )
      )
      correct_antwoord_gegeven(TRUE)
    } else {
      showModal(
        modalDialog(
          title = "Fout Antwoord",
          "Het antwoord is niet correct. Probeer het opnieuw."
        )
      )
    }
  })
  
  observe({
    if (correct_antwoord_gegeven() && input$wachtwoord == "jouwwachtwoord") {
      wachtwoord_ingevuld(TRUE)
    }
  })
  
  observeEvent(input$bevestig_naam, {
    if (input$naam != "") {
      showModal(
        modalDialog(
          title = "Gefeliciteerd!",
          paste("Bedankt,", input$naam, "! Klik op 'Open Document' om uw document te downloaden.")
        )
      )
    } else {
      showModal(
        modalDialog(
          title = "Fout",
          "Voer alstublieft uw naam in."
        )
      )
    }
  })
  
  output$document_output <- renderText({
    if (wachtwoord_ingevuld() || correct_antwoord_gegeven()) {
      paste("Dit is het document voor", input$naam)
    } else {
      ""
    }
  })
}

# Run de app
shinyApp(ui = ui, server = server)


Solution

  • For the conditionalPanel, you are using a condition which relies on input.wachtwoord_ingevuld. However, wachtwoord_ingevuld is an output value which you calculate on the server side, not an input value.

    Hence you have to rewrite your code using output.wachtwoord_ingevuld, see the example below which works.

    library(shiny)
    
    # Definieer raadsels en antwoorden
    raadsels <- c("Ik ben groot als ik jong ben, maar klein als ik oud ben. Wat ben ik?", 
                  "Ik ben altijd om je heen, maar nooit gezien. Wat ben ik?")
    antwoorden <- c("een boom", "lucht")
    
    # UI voor de spiegel
    ui <- fluidPage(
      titlePanel("Interactieve Spiegel"),
      tabsetPanel(
        tabPanel("Raadsel",
                 sidebarLayout(
                   sidebarPanel(
                     textInput("antwoord", "Wat is je antwoord?"),
                     actionButton("controleer", "Controleer Antwoord")
                   ),
                   mainPanel(
                     verbatimTextOutput("raadsel_output"),
                     verbatimTextOutput("feedback")
                   )
                 )
        ),
        tabPanel("Naam en Document",
                 sidebarLayout(
                   sidebarPanel(
                     conditionalPanel(
                       condition = "!output.wachtwoord_ingevuld",
                       passwordInput("wachtwoord", "Voer het wachtwoord in:"),
                       actionButton("ontgrendel", "Ontgrendel")
                     ),
                     conditionalPanel(
                       condition = "output.wachtwoord_ingevuld",
                       textInput("naam", "Vul je naam in:"),
                       actionButton("bevestig_naam", "Bevestig Naam"),
                       downloadButton("download_doc", "Open Document")
                     )
                   ),
                   mainPanel(
                     verbatimTextOutput("document_output_text")
                   )
                 )
        )
      )
    )
    
    # Server logica
    server <- function(input, output, session) {
      
      #wachtwoord_ingevuld <- reactiveVal(FALSE)
      correct_antwoord_gegeven <- reactiveVal(FALSE)
      
      output$raadsel_output <- renderText({
        raadsels[1]  # Weergeef het eerste raadsel
      })
      
      output$feedback <- renderText({
        if (correct_antwoord_gegeven()) {
          "Gefeliciteerd! Voer het wachtwoord in om verder te gaan."
        } else {
          ""
        }
      })
      
      observeEvent(input$controleer, {
        antwoord <- tolower(input$antwoord)  # Antwoorden zijn niet hoofdlettergevoelig
        
        if (antwoord %in% tolower(antwoorden)) {
          showModal(
            modalDialog(
              title = "Goed Geraden!",
              "Jullie mogen de envelop openen."
            )
          )
          correct_antwoord_gegeven(TRUE)
        } else {
          showModal(
            modalDialog(
              title = "Fout Antwoord",
              "Het antwoord is niet correct. Probeer het opnieuw."
            )
          )
        }
      })
      
      output$wachtwoord_ingevuld <- reactive({
        if (correct_antwoord_gegeven() && input$wachtwoord == "jouwwachtwoord") {
          TRUE
        } else {
          FALSE
        }
      })
      
      observeEvent(input$bevestig_naam, {
        if (input$naam != "") {
          showModal(
            modalDialog(
              title = "Gefeliciteerd!",
              paste("Bedankt,", input$naam, "! Klik op 'Open Document' om uw document te downloaden.")
            )
          )
        } else {
          showModal(
            modalDialog(
              title = "Fout",
              "Voer alstublieft uw naam in."
            )
          )
        }
      })
      
      document_output <- reactive({
        if (correct_antwoord_gegeven() || input$wachtwoord == "jouwwachtwoord") {
          paste("Dit is het document voor", input$naam)
        } else {
          ""
        }
      })
      
      output$document_output_text <- renderText({
        print(document_output())
      })
      
      outputOptions(output, "wachtwoord_ingevuld", suspendWhenHidden = FALSE)
    }
    
    # Run de app
    shinyApp(ui = ui, server = server)