0

I am trying to implement shiny popup as described in this post on shinyBS popup. My app is wrapped in an observeEvent() based on the Enter key and isolate() to prevent the table from changing as we type the name of cars before pressing Enter key.

The issue is that first time works well and I able to view the popup window, but consecutive searches with different car names and pressing Enter, the pop ups do not work. In fact, after a few attempts, the app greys out.

How to implement these 3 (pop up modal, observe event based on Enter key and isolate to prevent reactivity) in tandem seamlessly?

My code is as below

library(DT)
library(shiny)
library(shinyBS)
library(shinyjs)
library(shinydashboard)
library(tidyverse)

         shinyInput <- function(FUN, len, id, ...) {inputs <- character(len)
                      for (i in seq_len(len)) {
                     inputs[i] <- as.character(FUN(paste0(id, i), ...))}
                     inputs
                        }

         mtcarsDf <- mtcars %>%
                    mutate(car_name = row.names(mtcars)) %>%
                    select(car_name, cyl, mpg, gear)

     ui <- dashboardPage(
          dashboardHeader(),
          dashboardSidebar(
              sidebarMenu(
                menuItem("Tab1", tabName = "Tab1", icon = icon("dashboard"))
              )),

        dashboardBody(
             tags$script('
                         $(document).on("keyup", function(e) {
                          if(e.keyCode == 13){
                         Shiny.onInputChange("keyPressed", Math.random());
                             }
                            });
                           '),

     tabItems(
             tabItem(tabName = "Tab1",
               div("try typing mazda, ferrari, volvo, camaro, 
                     lotus, maserati, porsche, fiat, dodge, toyota, honda, merc"),
              textInput("name", "Car Name"),
              uiOutput("popup1"),
               DT::dataTableOutput('table1'))
                  )))



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

      observeEvent(input[["keyPressed"]], {

           data <- reactive({
              if (input$name != "") {
             reactiveDf <- reactive({
           if (input$name != "") {          
               mtcarsDf <- mtcarsDf %>%
                filter(grepl(input$name, car_name, ignore.case = TRUE))             
              }
            })

     testdata <- reactiveDf()
           as.data.frame(cbind(View = shinyInput(actionButton, nrow(testdata),
                                      'button_', label = "View", 
                                      onclick = 'Shiny.onInputChange(\"select_button\",  this.id)' ),
                    testdata))

         }
       }) 

     isolate(data <- data())#### this is required to avoid the table changing as we type the name    

        output$table1 <- DT::renderDataTable(data,
                                     selection = 'single',
                                     options = list(searching = FALSE,pageLength = 10),
                                     server = FALSE, escape = FALSE,rownames= FALSE)


    SelectedRow <- eventReactive(input$select_button,{
            as.numeric(strsplit(input$select_button, "_")[[1]][2])
               })


      observeEvent(input$select_button, {
               toggleModal(session, "modal1", "open")
                     })

      DataRow <- eventReactive(input$select_button,{
                  data[SelectedRow(),2:ncol(data)]
                })

         output$popup1 <- renderUI({
             bsModal("modal1", paste0("Data for Row Number: ",SelectedRow()), "", size = "large",
        column(12,                   
               DT::renderDataTable(DataRow())
            ))
       })

      })
    }
  shinyApp(ui, server)
R noob
  • 495
  • 3
  • 20

1 Answers1

1
library(shiny)
library(shinydashboard)
library(sqldf)
library(statquotes)
library(DT)
library(shinyBS)
library(shinyjs)
library(tidyverse)

shinyInput <- function(FUN, len, id, ...) {inputs <- character(len)
for (i in seq_len(len)) {
    inputs[i] <- as.character(FUN(paste0(id, i), ...))}
inputs
}

data(quotes)
quotes

ui <- dashboardPage(
    dashboardHeader(),
    dashboardSidebar(
        sidebarMenu(
            menuItem("TexSearch", tabName = "Tabs", icon = icon("object-ungroup"))) ),



    dashboardBody(
        tags$script('
                    $(document).on("keyup", function(e) {
                    if(e.keyCode == 13){
                    Shiny.onInputChange("keyPressed", Math.random());
                    }
                    });
                    '),
        shinyjs::useShinyjs(),
        #js function to reset a button, variableName is the button name whose value we want to reset
        tags$script("Shiny.addCustomMessageHandler('resetInputValue', function(variableName){
                    Shiny.onInputChange(variableName, null);
                    });
                    "),

        tabItem(tabName = "Tabs",
                fluidRow(
                    column(width=3, 
                           box(
                               title="Search ",
                               solidHeader=TRUE,
                               collapsible=TRUE,
                               width=NULL,
                               div("try typing data, history, visualization, graph, method, value"),
                               textInput("wordsearch", "Search"))),

                    column( width=9,
                            tabBox(
                                width="100%",
                                tabPanel("tab1", 
                                         uiOutput("quotepopup"),
                                         DT::dataTableOutput('table')
                                )))))))

server <- function(input, output, session) {
    #detach("package:RMySQL", unload=TRUE)



    observeEvent(input[["keyPressed"]], {

        ###get data from sql queries
        results <- reactive({
            if (input$wordsearch != "") {
                searches <- reactive({
                    if (input$wordsearch != "") {
                        sqldf(paste0("SELECT  qid, topic
                                     FROM quotes
                                     WHERE text LIKE '%",input$wordsearch,"%'"))

                    }
                })

                #### add view button
                testdata <- searches()
                as.data.frame(cbind(View = shinyInput(actionButton, nrow(testdata),
                                                      'button_', label = "View", 
                                                      onclick = 'Shiny.onInputChange(\"select_button\",  this.id)' ),
                                    testdata))
                }
                })

        results_ <<- results()

        ####pass data to datatable 
        output$table <- DT::renderDataTable(results_,
                                            selection = 'single',
                                            options = list(searching = FALSE,pageLength = 10),
                                            server = FALSE, escape = FALSE,rownames= FALSE)
        })

    ###update modal on clicking view button
    observeEvent(input$select_button, {
        s <- as.numeric(strsplit(input$select_button, "_")[[1]][2])

        rowselected <<- results_[input$table_rows_selected, "qid"]
        output$quotepopup <- renderUI({
            bsModal(paste('model', s ,sep=''), "Quote Details", "", size = "large",
                    column(12,                   
                           htmlOutput("clickedquotedetails")
                           # HTML("Hello")
                    )
            )
        })
        toggleModal(session, paste('model', s ,sep=''), toggle = "Assessment")
        session$sendCustomMessage(type = 'resetInputValue', message =  "select_button")
    })
    output$clickedquotedetails <- renderUI({




        selectedd <-  stringr::str_c(stringr::str_c("'", rowselected, "'"), collapse = ',')

        print(rowselected)
        print(selectedd)

        quotesearch <- reactive({

            sqldf(paste0("SELECT  *
                         FROM quotes
                         WHERE qid IN (",
                         selectedd,
                         ")"))
        })
        output = ""
        relevantquotes <- quotesearch()

        output <-
            paste(output,
                  "<b>Number of quotes: ",
                  as.character(dim(relevantquotes)[1]),
                  "</b>.<br/>")
        for (i in seq(from = 1,
                      to = dim(relevantquotes)[1])) {
            output <- paste(output,
                            paste("qid: ", relevantquotes[i, "qid"]),
                            sep = "<br/><br/>")
            output <- paste(output,
                            paste("topic: ", relevantquotes[i, "topic"]),
                            sep = "<br/><br/>")
            output <- paste(output,

                            paste("text: ", relevantquotes[i, "text"]),
                            sep = "<br/><br/><br/>")

        }
        HTML(output)
    })









    #end of observe ENTER event
}
shinyApp(ui, server)

Just copy paste this code..

  • is this solution working for you with the current versions of the loaded packages? it was working fine until i updated the packages recently. – R noob Mar 25 '21 at 17:50
  • don't know about that, but what is the error after updating this? and which package is problematic after the update? – Muhammad Awais Jun 25 '21 at 11:14