6

For some reason the displaying of bsModal content seems to go wrong when it is triggered by an observeEvent from the server side, images and or text don't appear, and it also seems to cause a disabling of Sweetalerts in some cases (which are basically prebuild modals).

I tagged shinyjs for this reason, since the app includes interaction with it. Besides a very long post, and complicated issue, I hope that the bsmodal part as well as the sweetalert coding with shinyJS, which is a copy of work by Dean Attali may help some other people who happen to read this. If you find it useful, give the post an upvote.

A full app with scenario 1, 2 and 3 is found below. Scenarios 4 and further are not in the full app, because some cause other parts of the app to stop working as well as soon as you add their code. I suggest to try the app at the end, and then read through my scenarios. (tried to make it as clear as possible.)

I'm using bsModals to add new functionality to my Shiny program (very large complex app), and discovered something strange while trying to incorporate images into bsmodals. I did some research into when the problem occurs, and present a test app here with several scenarios.

My primary issue:

For my purposes I need to figure out why scenario 7b doesn't work, i.e. bsmodal from server with image and observeEvent to activate it, 2nd main question is, can you somehow code the trigger = input$button1 argument in the bsmodal as trigger = values$variable somehow? I tried this but could not figure it out.

The main problem seems to revolve around the difference in behaviour of trigger = argument inside bsmodal() versus using observeEvent() with toggleModal()

Scenario 1: works

This on the UI side for instance works fine:

i.e. the modal appears, and the sweetalert in the app shows up on start

 actionButton("show1", "Show modal 1"),
 bsModal(id= 'InfoModal1',title = "This modal works", trigger = "show1", "triggered by clicking button 1, trigger argument in UI code for bsModal without image"),

Scenario 2: works

Adding an image to the modal, still all through UI side, works fine, image appears:

 actionButton("show2", "Show modal 2"),
 bsModal(id= 'InfoModal2',title = "This modal works", trigger = "show2",
                  img(src="https://www.rstudio.com/wp-content/uploads/2014/07/RStudio-Logo-Blue-Gradient.png", width="550", height="200"),
                  br(), "triggered by clicking button 2, trigger argument in UI code for bsModal"),

Scenario 3: works partially

Now we try to have it triggered by the server side of things. Which is usefull if it is for instance needed to have a modal that doesn't come from a button click, but a variable value changing. The modal appears, and this variation doesn't cause problems with the sweetalert, but no text content in the modal body!

ui side:

 actionButton("show3", "Show modal 3"),
 bsModal(id= 'InfoModal3',title = "This modal works but content text does NOT show up!", "triggered by clicking button 3, and use observeEvent in the server, without image"),

server side:

observeEvent(input$show3, { toggleModal(session, "InfoModal3", toggle = "toggle")  })

Scenario 4: does not work at all, and sweetalert now broken too

If I add an image to scenario 3, it's the same result. To do this I add the following code behind the senario 3 code in the UI and a second observer to the server, and I also notice, that if I don't run rm(UI) first, most of the time the ui will be wrong, i.e. without button nr 4

ui side

 actionButton("show4", "Show modal 4"),
          bsModal(id= 'InfoModal4',title = "This modal works but content image does NOT show up!", img(src="https://www.rstudio.com/wp-content/uploads/2014/07/RStudio-Logo-Blue-Gradient.png", width="550", height="200"),"triggered by clicking button 4, trigger modal by observeEvent in the server, without image")

server side:

observeEvent(input$show4, { toggleModal(session, "InfoModal4", toggle = "toggle")  })

Scenario 5: WORKS -> build basic bsModal with renderUI() with trigger in it from the server side

replace whole tabitems() section in working app with this in the UI:

tabItems(
      tabItem(tabName = 'tab1',
              actionButton("show5", "Show modal 5"),
              uiOutput("MyModal5")
    ))))

and replace server with:

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

  shinyjs::js$swal( title = '<span style="color:#339FFF; font-size: 30px">Finished loading app<span>',
                    text = '<span style="color:black; font-size: 16px">version: 1.0.0 <br> written by: M.A. van Dijk<span>',
                    imageUrl= "https://www.rstudio.com/wp-content/uploads/2014/07/RStudio-Logo-Blue-Gradient.png" )

  output$MyModal5 <- renderUI({  bsModal(id= 'InfoModal5',title = "This modal works but content text does NOT show up!", trigger = "show5", " build by server, and triggered by clicking button 5 with trigger argument in modal, without image") })
}

Scenario 6: works with or without image, but.....

ui part is :

tabItems(
      tabItem(tabName = 'tab1',
              actionButton("show6", "Show modal 6"),
              uiOutput("MyModal6")
    ))))

server part after the swal function:

 output$MyModal6 <- renderUI({ bsModal(id= 'InfoModal6',title = "This modal works and content text does show up!", trigger = "show6", " build by server, and triggered by clicking button 6 and an observeEvent in the server, without image") })
 }

or the version of server WITH image:

output$MyModal6 <- renderUI({ bsModal(id= 'InfoModal6',title = "This modal works and content text does show up!", trigger = "show6", img(src = "https://www.rstudio.com/wp-content/uploads/2014/07/RStudio-Logo-Blue-Gradient.png", width="550", height="200"),  
                      "build by server, and triggered by clicking button 6 and a trigger argument in the bsmodal, with image") })

*I can't use this in my program however when I want to have the modal triggered by a variable rather than a button click. To do that, I should use an observeEvent like the next scenario, I think. Unless there is a way to use "trigger = "some reactive value" *

Scenario 7: Works, without an image, not with....

I found out that it does work with an observeEvent(input$show7) instead of trigger = "show7" in the dummy app to do everything from the server, until I add an img(scr.... part. ui side:

tabItems(
  tabItem(tabName = 'tab1',
          actionButton("show7", "Show modal 7"),
          uiOutput("MyModal7")
))))

server side

output$MyModal7 <- renderUI({ bsModal(id= 'InfoModal7',title = "This modal works and content text does show up!", "build by server, and triggered by clicking button 7 and a trigger argument in the bsmodal, with image") })

  observeEvent(input$show7, { toggleModal(session, "InfoModal7", toggle = "toggle")  })

. .To add the image, replace the output$modal7 with

output$MyModal7 <- renderUI({ bsModal(id= 'InfoModal7',title = "This modal doesn't work",                                   img(src="https://www.rstudio.com/wp-content/uploads/2014/07/RStudio-Logo-Blue-Gradient.png", width="550", height="200"),
                                        "build by server, and triggered by clicking button 7 and a trigger argument in the bsmodal, with image") })

. . .

WORKING APP FOR Scenario 1, 2 and 3:

library(shiny)
library(shinyBS)
library(shinyjs)

jscode <- "
shinyjs.swal = function(params) { 
  var defaultParams = {
title: null,
text : null,
imageUrl: null
};
params = shinyjs.getParams(params, defaultParams);
swal({title : params.title, text : params.text,  imageUrl : params.imageUrl,
imageSize: '400x400',  
html: true,
showCancelButton : false,
showConfirmButton : true,
closeOnConfirm: true,
confirmButtonColor: '#339FFF',
allowOutsideClick: true   }); };"

ui <- shinydashboard::dashboardPage(

  dashboardHeader(title = "Dummy App"),
    dashboardSidebar(
      tags$head(
        tags$script(src = "https://cdnjs.cloudflare.com/ajax/libs/sweetalert/1.0.1/sweetalert.min.js"),   ### code for the sweetalerts
        tags$link(rel = "stylesheet", type = "text/css",                                                  ### code for the sweetalerts
                href = "https://cdnjs.cloudflare.com/ajax/libs/sweetalert/1.0.1/sweetalert.min.css")    ### code for the sweetalerts
        ),

  sidebarMenu(id = 'sidebarmenu',
                menuItem("My Tab", tabName = 'tab1'))),

  dashboardBody(
    shinyjs::useShinyjs(),     ### code for the sweetalerts
    shinyjs::extendShinyjs(text = jscode),  ### code for the sweetalerts

    tabItems(
      tabItem(tabName = 'tab1',

          actionButton("show1", "Show modal 1"),
          bsModal(id= 'InfoModal1',title = "This modal works", trigger = "show1", "triggered by clicking button 1, trigger argument in UI code for bsModal without image"),

          actionButton("show2", "Show modal 2"),
          bsModal(id= 'InfoModal2',title = "This modal works", trigger = "show2",
                  img(src="https://www.rstudio.com/wp-content/uploads/2014/07/RStudio-Logo-Blue-Gradient.png", width="550", height="200"),
                  br(), "triggered by clicking button 2, trigger argument in UI code for bsModal"),

          actionButton("show3", "Show modal 3"),    

          bsModal(id= 'InfoModal3',title = "This modal works but content text does NOT show up!", "triggered by clicking button 3, trigger modal by observeEvent in the server, without image")

      ))))

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

  shinyjs::js$swal( title = '<span style="color:#339FFF; font-size: 30px">Finished loading app<span>',
                     text = '<span style="color:black; font-size: 16px">version: 1.0.0 <br> written by: M.A. van Dijk<span>',
                     imageUrl= "https://www.rstudio.com/wp-content/uploads/2014/07/RStudio-Logo-Blue-Gradient.png" )

    observeEvent(input$show3, { toggleModal(session, "InfoModal3", toggle = "toggle")  })


}
shinyApp(ui = ui, server = server)
Mark
  • 2,789
  • 1
  • 26
  • 66

0 Answers0