rstudio / shiny

Easy interactive web applications with R
https://shiny.posit.co/
Other
5.37k stars 1.86k forks source link

Serverless Modal #3558

Open Mosk915 opened 2 years ago

Mosk915 commented 2 years ago

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)
stla commented 2 years ago

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 commented 2 years ago

There is ModalDialogUI in the shinyGizmo package.