This is a follow-up question to this question from 4 years ago: How to close embedded modalDialog
library(shiny)
library(DT)
library(shinyWidgets)
library(shinyalert)
ui = fluidPage(
fluidRow(
column(width = 6,
actionButton('button',
label = "Click me",
icon = icon("fas fa-check"),
width = '100%')
)
)
)
server = function(input, output) {
observeEvent(input$button, {
showModal(
modalDialog(
title = "Test two modalDialogs",
br(),
autonumericInput("numeric",
"Enter a number less than 69",
value = NULL,
width = '100%'),
actionButton("buttonA",
label = "Click to see what happens",
icon = icon("fas fa-save")
),
footer = NULL
)
)
})
observeEvent(input$buttonA, {
if(input$numeric < 69){
showModal(
modalDialog(
title = h2("You did not enter a number which is greater than 69. Please try again."),
actionButton("buttonB",
label = "Ok."),
footer = tagList(modalButton("Try again"))
)
)
}
})
observeEvent(input$buttonB, {
removeModal()
})
}
shinyApp(ui = ui, server = server)
Is it by now possible to close only the second modal-dialog which opens after the user entered a value smaller than 69? Both options, the modalButton and also the removeModal close both dialogs.
Related
I want to develop a feature that when opening the switch the image can show outside of the page and when closing the switch, the image is hidden. Here is my sample code for showing/hiding the image in the page but if we can make the image be a floating window and can be moved around the exiting app page?
library("shinydashboard")
library("shinyWidgets")
ui <- fluidPage(
h4("Embedded image"),
uiOutput("img"),
fluidRow(
tags$h4("Show and Hide Image"),
materialSwitch(
inputId = "get_image",
label = "Show Image",
value = FALSE,
status = "success"
),
),
)
server <- function(input, output, session) {
observeEvent(input$get_image, {
if(input$get_image == TRUE){
output$img <- renderUI({
tags$img(src = "https://www.r-project.org/logo/Rlogo.png")
})
}else{
output$img <- NULL
}
})
}
shinyApp(ui, server)
Something like this?
library(shiny)
library("shinydashboard")
library("shinyWidgets")
ui <- fluidPage(
h4("Embedded image"),
uiOutput("img"),
fluidRow(
tags$h4("Show and Hide Image"),
materialSwitch(
inputId = "get_image",
label = "Show Image",
value = FALSE,
status = "success"
),
),
)
server <- function(input, output, session) {
output$img <- renderUI({
if(input$get_image)
absolutePanel(
tags$img(src = "https://www.r-project.org/logo/Rlogo.png", width = "512"),
draggable = TRUE
)
})
}
shinyApp(ui, server)
I would like to control the phone number by showing a notification :
If the user type a wrong number (like "aaaa")
If the user type a long number (greater than 10 digits)
I used the function showNotification from shiny with closeButton = FALSE and duration = NULL.
When the user type a wrong number, the notification popped up but when he type a long number the the notification also popped up but the previous one does not disappear
I would like to show only one notification (wrong number or long number) but not the both at the same time. How can we do that ? Here's my apps :
library(shiny)
library(shinydashboard)
library(shinydashboardPlus)
############# UI ############
body <- dashboardBody(
tabItems(
tabItem(tabName = "tab1",
fluidRow(
tags$h1('my title'),
textInput("phone_number", "enter your phone number", value = ""),
actionButton("button", "go")
)
)
)
)
ui <- dashboardPage(
title = "Example",
options = list(sidebarExpandOnHover = TRUE),
header = dashboardHeader(disable = FALSE),
sidebar = dashboardSidebar(
minified = TRUE, collapsed = TRUE,
sidebarMenu(id="menu",
menuItem("first tab", tabName = "mytab", icon = icon("fas fa-acorn"),
menuSubItem('menu1',
tabName = 'tab1',
icon = icon('fas fa-hand-point-right'))
)
)
),
body
)
############# SERVER ############
server <- function(input, output) {
observeEvent(
input$button,
{
if(is.na(as.numeric(input$phone_number))) {
showNotification(type = "error",
duration = NULL,
closeButton = FALSE,
"wrong number")
} else if(nchar(input$phone_number)<10) {
showNotification(type = "error",
duration = NULL,
closeButton = FALSE,
"too long (10 digits required)")
}
}
)
}
############# RUN THE APP ############
shinyApp(ui = ui, server = server)
Some help would be appreciated
I would not use a notification here, because they will always be displayed for a fixed time duration and at a different position of the window, which might confuse the user. I would just render the message in using a textOutput:
library(shiny)
library(shinyjs)
ui <- fluidPage(
useShinyjs(),
textInput("phone_number", "phone number"),
textOutput("phone_notification")
)
server <- function(input, output, session) {
output$phone_notification <- renderText({
if(input$phone_number == "") {
"" # empty is ok
}
else if(is.na(as.numeric(input$phone_number))) {
"wrong number"
} else if (nchar(input$phone_number) > 10) {
"too long"
} else {
"" # correct number
}
})
}
shinyApp(ui, server)
You can also style the text e.g. to make it red:
ui <- fluidPage(
useShinyjs(),
textInput("phone_number", "phone number"),
tagAppendAttributes(
textOutput("phone_notification"),
style = "color:red"
)
)
I needed the solution OP asked. I found the following code snippet to work in my case:
removeNotification(id = "onlyOnce", session = getDefaultReactiveDomain())
showNotification("Show me once", id = "onlyOnce")
See also: https://search.r-project.org/CRAN/refmans/shiny/html/showNotification.html
I wish to have a popout modal within a shiny app that depending on the user's action within the modal,
it would show or hide certain fields.
For example, the Modal includes a button that when pressed, another button would apear\disappear.
sadly, although the observeEvent detects a change in the hide\show button, shinyjs::toggle(), shinyjs::hide()
and shinyjs::show() fail to work
example script:
library(shiny)
ui <- fluidPage(
actionButton("show_modal", "show modal"),
)
server <- function(input, output) {
observeEvent(input$show_modal, {
showModal(
modalDialog(footer = NULL,easyClose = T,
tagList(
fluidRow(
box(status = "primary", width = 6, style = "direction: ltr",
actionButton("toggle_btn", "show or hide second button")
)),
fluidRow(
box(status = "success", width = 6, style = "direction: ltr",
actionButton("box_btn", "Box!")
))
)
))
})
observeEvent(input$toggle_btn, {
shinyjs::toggle("box_btn")
cat("\npresentation button pressed\n")
})
}
shinyApp(ui, server)
You can do it without shinyjs by using conditionalPanel():
library(shiny)
ui <- fluidPage(
actionButton("show_modal", "show modal"),
)
server <- function(input, output) {
rv <- reactiveValues(show_btn = FALSE)
observeEvent(input$toggle_btn, {
rv$show_btn <- !rv$show_btn
})
output$show_btn <- reactive({rv$show_btn})
outputOptions(output, "show_btn", suspendWhenHidden = FALSE)
observeEvent(input$show_modal, {
# add_path_to_existing_offers_DB(user = user)
showModal(
modalDialog(
footer = NULL,
easyClose = T,
tagList(
fluidRow(
actionButton("toggle_btn", "show or hide second button")
),
conditionalPanel(
condition = "output.show_btn == true",
fluidRow(
actionButton("box_btn", "Box!")
)
)
)
)
)
})
}
shinyApp(ui, server)
Turns out as Dean Attali the author of shinyjs pointed out kindly,
that I failed to call useShinyjs() function.
library(shiny)
library(shinyjs)
ui <- fluidPage(
**useShinyjs(),**
actionButton("show_modal", "show modal"),
)
server <- function(input, output) {
observeEvent(input$show_modal, {
showModal(
modalDialog(footer = NULL,easyClose = T,
tagList(
fluidRow(
box(status = "primary", width = 6, style = "direction: ltr",
actionButton("toggle_btn", "show or hide second button")
)),
fluidRow(
box(status = "success", width = 6, style = "direction: ltr",
actionButton("box_btn", "Box!")
))
)
))
})
observeEvent(input$toggle_btn, {
shinyjs::toggle("box_btn")
cat("\npresentation button pressed\n")
})
}
shinyApp(ui, server)
I would like to have one of the tabPanels in my Shiny app launch a shinyFiles style input. In this case I would like to launch a shinySaveButton, without the shinySaveButton being in my dataset (By clicking the save icon [which is actually a tabPanel])
Reproducible example below
library(shiny)
library(shinyFiles)
ui <- navbarPage('Test App',id = "inTabset", selected="panel1",
tabPanel(title = "", value = "Save", icon = icon("save")),
tabPanel(title = "Panel 1", value = "panel1",
h1("Panel1")),
tabPanel(title = "Panel 2",value = "panel2",
h1("Panel2"))
)
server <- function(input, output, session) {
values = reactiveValues(tabSelected="panel1")
observe({
if (input$inTabset=="Save") {
updateNavbarPage(session,"inTabset",selected=values$tabSelected)
#CODE FOR LOADING SHINYFILES DIALOG IN HERE
} else {
values$tabSelected<-input$inTabset
}
})
}
shinyApp(ui, server)
Any help would be greatly appreciated.
Work around using hidden element trick
library(shiny)
library(shinyFiles)
library(shinyjs)
jsCode<-"shinyjs.saveButton=function(){ $('#buttonFileSaveHidden').click(); }"
ui <- fluidPage(
useShinyjs(),
extendShinyjs(text = jsCode),
navbarPage('Test App',id = "inTabset", selected="panel1",
tabPanel(title = "", value = "Save", icon = icon("save")),
tabPanel(title = "Panel 1", value = "panel1",
h1("Panel1")
),
tabPanel(title = "Panel 2",value = "panel2",
h1("Panel2"))
),
# HIDDEN BUTTON TO INITIATE THE SAVE
hidden(shinySaveButton( "buttonFileSaveHidden",
label="",
title="Save as ...",
list('hidden_mime_type'=c("R")),
class='hiddenButton')),
wellPanel( #ONLY INCLUDED TO DISPLAY OF PATH INFO OF THE CHOICE
h3('Current save path info'),
tableOutput('table')
)
)
server <- function(input, output, session) {
values = reactiveValues(tabSelected="panel1")
observe({
if (input$inTabset=="Save") {
updateNavbarPage(session,"inTabset",selected=values$tabSelected)
#CODE FOR LOADING SHINYFILES DIALOG IN HERE
js$saveButton()
} else {
values$tabSelected<-input$inTabset
}
})
shinyFileSave(input, "buttonFileSaveHidden", session=session, roots=c(wd="~"), filetypes=c('R') ) #hidden
# GET THE SAVE PATH CHOICE AND RECORD IT IN fp.dt.rv
fp.dt.rv<-reactiveVal("")
observeEvent(input$buttonFileSaveHidden,{
fp.dt<-parseSavePath(c(wd='~'), input$buttonFileSaveHidden)
fp.dt.rv(fp.dt) #or just use to immediately write.
})
# ONLY TO DISPLAY THE SAVE CHOICE
output$table <- renderTable(fp.dt.rv())
}
shinyApp(ui, server)
I want to execute rest of shiny app code only when modal dialog box is closed. How can I achieve this?
Here simple code:
# ui.R
actionButton("loadData", label = "Button", icon = icon("mail-forward"))
# server.R
observeEvent(input$loadData, {
showModal(modalDialog(
title = modal.title,
textInput("newName", "Enter file name:", value = ""),
easyClose = TRUE,
footer = list(
actionButton("confirmName", "OK"),
modalButton("Cancel"))
))
# ...code to be executed after modal is closed...
})
Create an event handler that executes code when the OK action button has been clicked, and also closes the modal using removeModal.
library(shiny)
ui <- fluidPage(
actionButton("loadData", label = "Button", icon = icon("mail-forward")),
verbatimTextOutput("filename")
)
server <- function(input, output, session) {
observeEvent(input$loadData, {
showModal(modalDialog(
title = "title",
textInput("newName", "Enter file name:", value = ""),
easyClose = TRUE,
footer = list(
actionButton("confirmName", "OK"),
modalButton("Cancel"))
))
})
output$filename <- eventReactive(input$confirmName, {
message("Closing modal")
removeModal()
input$newName
})
}
shinyApp(ui, server)
There's an example of this in the docs: https://shiny.rstudio.com/reference/shiny/latest/modalDialog.html