我正在寻找一种方法,当 easy-close 选项为 TRUE 时,基于关闭 Shiny modal 来触发事件(因此在 modal 外部单击将关闭它)。由于没有链接到模式的 ID,我似乎无法捕捉到这个事件。我尝试在“观察”事件中包装模态,但这只会触发模态的打开而不是关闭。
示例:如果通过单击外部模式关闭此模式,我想触发一个事件,而不是关闭按钮。下面的代码仅在打开时触发...
library(shiny)
ui <- fluidPage(
fluidRow(
actionButton(inputId = "enterText", label = "Enter name", align = "left"),
h1(textOutput("myOutput"))
)
)
server <- function(input, output, session) {
myText <- reactiveValues(input = "...")
myModal = modalDialog(h3("Enter a string, then click outside this modal to close and display the text"),
textInput(inputId = "myString", label = "Enter a string: "),
title = "Input", easyClose = TRUE, footer = modalButton("Dismiss"))
test = observe(myModal)
#Open the modal when button clicked
observeEvent(input$enterText,{
showModal(myModal)
})
#Observe the modal, should fire when it CLOSES by clicking outside the modal (easy-close)
observeEvent(test, {
myText$input = input$myString
print("observed")
}, ignoreInit = T)
output$myOutput = renderText(myText$input)
}
shinyApp(ui = ui, server = server)
我想为不需要像 OP 那样使用 easyClose = TRUE 的任何人提供一个更简单的答案——在这种情况下,这是一个比 SBista 在评论中的链接更简单的解决方案。
这只是用您自己的操作按钮替换了模态框的默认“关闭”按钮,这样您就可以在关闭模态框时执行一些额外的操作。这是通过
footer =
参数设置的。
在本例中,模态框包含复选框,只有在模态框关闭后复选框才会生效。
library(shiny)
shinyApp(
ui <- fluidPage(
fluidRow(
## Button to display modal:
actionButton(inputId = "display_modal",label = "Display modal"),
## Print the choices that were made in the modal:
h1(textOutput("checked_letters"))
)
),
server <- function(input, output) {
## These values allow the actions made in the modal to be delayed until the
# modal is closed
values = reactiveValues(to_print = "", ## This is the text that will be displayed
modal_closed=F) ## This prevents the values$to_print output from
# updating until the modal is closed
## Open the modal when button clicked
observeEvent(input$display_modal,{
values$modal_closed <- F
showModal(modalDialog(
checkboxGroupInput("checkboxes",label = "Select letters",
choices = LETTERS[1:7]),
## This footer replaces the default "Dismiss" button,
# which is 'footer = modalButton("Dismiss")'
footer = actionButton("dismiss_modal",label = "Dismiss")
))
})
## This event is triggered by the actionButton inside the modalDialog
# It closes the modal, and by setting values$modal_closed <- T, it
# triggers values$to_print to update.
observeEvent(input$dismiss_modal,{
values$modal_closed <- T
removeModal()
})
## values$to_print is only updated once the modal is closed.
observe({
if(values$modal_closed){
values$to_print <- paste(input$checkboxes)
}
})
## Forward the values$to_print to the UI
output$checked_letters = renderText({values$to_print})
}
)
与第一个答案类似,我的方法只适用于
easyClose = FALSE
。我们可以创建一个自定义函数 actionButton
,而不是将 observeEvent
与 modalActionButton
一起使用,这基本上是从 actionButton
复制粘贴并添加 data-dismiss = "modal"
:
我改编了下面第一个答案的例子:
library(shiny)
# this is basically copied from actionButton() and just "`data-dismiss` = "modal"
# from modalButton() is added:
modalActionButton <- function(inputId, label, icon = NULL, width = NULL, ...) {
value <- restoreInput(id = inputId, default = NULL)
tags$button(id = inputId, type = "button", style = if (!is.null(width))
paste0("width: ", validateCssUnit(width), ";"), type = "button",
class = "btn btn-default action-button", `data-dismiss` = "modal", `data-val` = value,
list(shiny:::validateIcon(icon), label), ...)
}
shinyApp(
ui <- fluidPage(
fluidRow(
## Button to display modal:
actionButton(inputId = "display_modal",label = "Display modal"),
## Print the choices that were made in the modal:
h1(textOutput("checked_letters"))
)
),
server <- function(input, output) {
values = reactiveValues(to_print = "") ## This is the text that will be displayed
observeEvent(input$display_modal, {
showModal(modalDialog(
checkboxGroupInput("checkboxes",label = "Select letters",
choices = LETTERS[1:7]),
title = "This is a modal page with a 'modalActionButton' ",
size = "l",
easyClose = FALSE,
# here is the modalActionButton
footer = modalActionButton("close",
"Close")
))
})
observeEvent(input$close, {
values$to_print <- input$checkboxes
})
## Forward the values$to_print to the UI
output$checked_letters <- renderText({values$to_print})
}
)
我来晚了一点-但是,我最近不得不解决类似的问题。我们可以通过监听 bootstrap 模态类提供的 JS 事件 来触发 shiny 事件——以下也适用于
easyClose = TRUE
:
library(shiny)
ui <- fluidPage(
tags$script(HTML(
"$(document).on('shown.bs.modal','#shiny-modal', function () {
Shiny.setInputValue(id = 'modal_visible', value = true);
});
$(document).on('hidden.bs.modal','#shiny-modal', function () {
Shiny.setInputValue(id = 'modal_visible', value = false);
});"
)),
fluidRow(
actionButton(
inputId = "enterText",
label = "Enter name",
align = "left"
),
h1(textOutput("myOutput"))
))
server <- function(input, output, session) {
myText <- reactiveValues(input = "...")
myModal <- modalDialog(
h3(
"Enter a string, then click outside this modal to close and display the text"
),
textInput(inputId = "myString", label = "Enter a string: "),
title = "Input",
easyClose = TRUE,
footer = modalButton("Dismiss")
)
# Open the modal when button clicked
observeEvent(input$enterText, {
showModal(myModal)
})
observe({print(input$modal_open)})
# Observe the modal, should fire when it CLOSES by clicking outside the modal (easy-close)
observeEvent({input$modal_visible == FALSE}, {
myText$input <- input$myString
}, ignoreInit = TRUE)
output$myOutput = renderText({myText$input})
}
shinyApp(ui = ui, server = server)
此外,这个答案对到达这里很有用。