shiny icon indicating copy to clipboard operation
shiny copied to clipboard

Serverless Modal

Open Mosk915 opened this issue 4 years ago • 2 comments

It would be useful if there was a function to create a modal and show/hide it without needing to generate the modal on the fly through the server every time. This would be useful when the content of the modal needs to persist between views.

The shinyBS package has the bsModal function which basically does what I'm talking about but doesn't have the same level of customization as the standard modalDialog function.

I mocked up a rough idea of how this could work using html and javascript.

library(shiny)

ui <- fluidPage(
  actionButton("showModal", "Show Modal"),
  tags$div(id = "modal",
           class = "modal in",
           style = "display: none;",
           tags$div(class = "modal-dialog",
                    style = "width: 95%;",
                    tags$div(class = "modal-content",
                             tags$div(class = "modal-header",
                                      tags$h4(class = "modal-title",
                                              "Modal Title",
                                              tags$button(id = "close-modal",
                                                          type = "button",
                                                          class = "btn btn-default action-button shiny-bound-input",
                                                          style = "float: right; background-color: transparent; border: none;",
                                                          tags$i(class = "fa fa-times",
                                                                 role = "presentation",
                                                                 `aria-label` = "times icon")))),
                             tags$div(class = "modal-body",
                                      "[Modal Content]")))),
  tags$script("var modal = document.getElementById('modal');
                                document.getElementById('showModal').onclick = function() {
                                  modal.style.display = 'block';
                                  document.getElementsByTagName('body')[0].classList.add('modal-open');
                                }
                                document.getElementById('close-modal').onclick = function() {
                                  modal.style.display = 'none';
                                  document.getElementsByTagName('body')[0].classList.remove('modal-open');
                                }
                                window.onclick = function(event) {
                                  if (event.target == modal) {
                                    modal.style.display = 'none';
                                    document.getElementsByTagName('body')[0].classList.remove('modal-open');
                                  }
                                }")
)

server <- function(input, output, session) {
  
}

shinyApp(ui, server)

Mosk915 avatar Dec 12 '21 00:12 Mosk915

You can try my package shinyChakraUI, but it is a bit complicated to use.

library(shiny)
library(shinyChakraUI)

ui <- chakraPage(
  
  br(),
  
  chakraComponent(
    "mycomponent",
    
    chakraModal(
      inputId = "modal",
      openButton = Tag$Button(
        colorScheme = "orange",
        "Open Modal"
      ),
      header = Tag$ModalHeader(
        fontSize = "lg",
        fontWeight = "bold",
        "Modal title"
      ),
      body = Tag$ModalBody(
        Tag$RadioGroup(
          id = "radiogrp",
          value = "3",
          Tag$Stack(
            direction = "row", 
            Tag$Radio(value = "1", "First"),
            Tag$Radio(value = "2", "Second"),
            Tag$Radio(value = "3", "Third")
          )
        ),
      ),
      footer = Tag$ModalFooter(
        Tag$ButtonGroup(
          spacing = "3",
          Tag$Button(
            action = "close",
            value = "CLOSE",
            "Close"
          ),
          Tag$Button(
            action = "cancel",
            colorScheme = "red",
            "Cancel"
          )
        )
      )
    )
    
  )
  
)

server <- function(input, output, session){
  
  observe({
    print(input[["modal"]])
    print(input[["radiogrp"]])
  })
  
}

shinyApp(ui, server)

chakraModal

stla avatar Dec 14 '21 21:12 stla

There is ModalDialogUI in the shinyGizmo package.

stla avatar May 20 '22 12:05 stla