0

I am building a big and (for me) complicated r shiny app where I am allowing people to categorize a long list of texts.

Whenever they want to add a previously non-existent label to a category, a modalDialog pops up. Not important now what all needs to be done in that dialog. That is under control. (I want to thank the entire Stackoverflow community: with the help of questions and answers posted earlier I pieced together my solution - this is an awesome platform).

However, here is the problem: first text that gets a new category, the modalDialog pops up, allows for all the necessary actions and performs what is needed when the 'save' button is hit. Same for the cancel button.

Then the second time the modalDialog should be called, it briefly appears, but then immediately closes of its own accord (via the same event as was used to close the dialog the first time). The third time everything is fine again. The fourth time I get the flash-situation, etc. Also, the amount of times that that closing event is executed increases with each trial?

I reproduced the situation in the simplified code below. Click on Button 1, it opens and shows the appropriate information. Click on Save, it closes (and shows the debugging message just once). Click on Button 2: flash! (and two times the debugging message). Click on Button 2 again (or 1, whatever): all is fine.

I tried making the code in the observeEvents conditional. I tried passing the session to the removeModal-function. Did not work. Tried using modalButtons instead of actionButtons, but they don't have an id and then I cannot catch the click. And save and cancel should not just close the modal.They need to execute some code (in the real version) so i need to be able to distinguish between them.

Could someone give me a hint? It would be so much appreciated! This code gets itself in a loop somehow and would like to get it out of there.

library(shiny)

ui <- (fluidPage(
  actionButton(inputId = "button1", label = "Button 1"),
  actionButton(inputId = "button2", label = "Button 2")
))

server <- function(session, input, output) {
  observeEvent(input$button1, {
    session = session
    modalId = 'newLabel'
    label = "button1"
    text = "This is text 1"
    myToggleModal(session, modalId, label, text)
  })
  
  observeEvent(input$button2, {
    session = session
    modalId = 'newLabel'
    label = "button2"
    text = "This is text 2"
    myToggleModal(session, modalId, label, text)
  })
  
  myToggleModal <- function(session, modalId, label, text){
    varLabel <- label
    varText <- text
    
    showModal(
      tagList(
        modalDialog(
          title = '',
          htmlOutput(outputId = "output1"),
          hr(),
          htmlOutput("output2"),
          br(),br(),
          footer = tagList(
            actionButton("cancel", "Cancel"),
            actionButton("save", "Save")
          )
        )
      )
    )
    
    
    output$output1 <- renderUI({
      varLabel
    })
    
    output$output2 <- renderUI({ # display the marked-up text
      text
    })
    
    observeEvent(input$save,{
      ##do something
      
      #print the debugging message
      print("you are passing the save event")
      removeModal()
    })
    
    observeEvent(input$cancel,{
      ##don't do that something
      
      #print the debugging message
      print("you are passing the cancel event")
      removeModal()
    })
  }
}
  
shinyApp(ui, server)
samsmit
  • 1
  • 4

1 Answers1

0

Here is part of the answer: I should have identified the namespace for the actionbuttons in the module. I adapted using modal window in Shiny module for my code and that works. Still need to find a new way to pass information to the module now, but that was not pertinent to this particular question.

modalModuleUI <- function(id, label) {
  ns <- NS(id)
  actionButton(ns(label), gsub(pattern = "button", x = label, replacement = "Button "))
}

modalModule <- function(input, output, session) {
  
  myModal <- function() {
    ns <- session$ns
      modalDialog(
        title = '',
        htmlOutput(outputId = ns("output1")),
        hr(),
        htmlOutput(ns("output2")),
        br(),br(),
        footer = tagList(
          actionButton(ns("cancel"), "Cancel"),
          actionButton(ns("save"), "Save")
        )
      )
  }
  
  # open modal on button click
  observeEvent(input$button1,
               ignoreNULL = TRUE, {
                 showModal(myModal())
               }
  )
  
  observeEvent(input$button2,
               ignoreNULL = TRUE, {
                 showModal(myModal())
               }
  )
  
  # close modal on button click
  observeEvent(input$save, { 
    print("save")
    removeModal() 
  })
  
  observeEvent(input$cancel, { 
    print("cancel")
    removeModal() 
  })
}


ui <- fluidPage(
  modalModuleUI("foo", "button1"), 
  modalModuleUI("foo", "button2")
  )

server <- function(input, output, session) {
  callModule(modalModule, "foo")
}
  
shinyApp(ui, server)
samsmit
  • 1
  • 4