Creating a pop-up window in Shiny that activates when switching tabs

Is there a way to create a popover/tooltip in a Shiny app that automatically appears when users switch to a specific tab containing a data table? I have tried using the shinybs package to create a popover that shows on click or hover, but I need it to appear without any interaction. I believe the trigger = "manual" option might help, but I'm not sure how to implement a manual trigger. I'm open to alternative solutions that achieve the same outcome.

Additionally, I would like the popover to be positioned in a way that it points to a particular row in the data table. In the past, I have used the rowCallback = JS(rowCallback) parameter with the shinyjs package to add hover-over tooltips to rows, but I'm unsure if this can be modified to show tooltips without hovering.

Lastly, I need a way to close the popover/tooltip. Any guidance on this would be greatly appreciated.

Below is a basic example with a shinybs popover triggered by a click (which is not the desired behavior):

library(shiny)
library(shinyBS)
library(DT)

data <- as.data.frame(rbind(c(1,2,3), c(4,5,6)))
colnames(data) <- c("Var1", "Var2", "Var3")

ui <- navbarPage(
  title = "Title", id = "navbar", 
  tabsetPanel(id="tabs", 
              tabPanel(value = "tab1", title = "Tab1",
                       actionButton("action1", "Switch tabs")
                       ),
              
  )
)

server <- function(input, output, session) {
    observeEvent(input$action1, {
      insertTab(inputId = "tabs", target = "tab1", select=T,
                tabPanel(value = "tab2", title = "Tab2",
                         dataTableOutput("table1"),
                         bsPopover(id="table1", title="A popover",
                                   placement = "bottom", trigger = "click")
                ) 
      )
    })
  
  output$table1 <- renderDataTable({
    datatable(data)
  })
}

shinyApp(ui, server)

Answer №1

Let's give this a try:

  1. Start by defining a function (make_popover) that will insert the necessary HTML to generate a popover element (refer to the Bootstrap Popover Docs). Make sure to set data-trigger to manual to enable manual triggering.
  2. Replace a single cell in the table with this markup and utilize escape = FALSE in datatable to prevent escaping of this HTML.
  3. Integrate an observer that triggers upon tab change and invokes a JS function to display the popover. You could consider using shinyjs but for this solution, we will use the conventional shiny method by employing addCustomMessageHandler.
  4. Also, implement a click handler to close the popover as soon as a click on the second panel is detected.
library(shiny)
library(DT)

my_data <- data.frame(
   a = c(1, 4),
   b = c(2, 5),
   c = c(3, 6)
)

js <- HTML("
   $(function () {
      $('[data-toggle=\"popover\"]').popover({});
      $('div[data-value=\"tab2\"]').on('click', () => $('[data-toggle=\"popover\"]').popover('hide'));
   });
   Shiny.addCustomMessageHandler('show_popover', function(message) {
      setTimeout(() => $('[data-toggle=\"popover\"]').popover('show'), 100); // timeout needed to avoid that the element is not shown yet
   })"
)

make_popover <- function(x, title, content) {
   a(x,
     style = "text-decoration: none; color: inherit;",
     "data-toggle" = "popover",
     "data-trigger" = "manual",
     title = title,
     "data-content" = content) %>% 
      as.character()   
}

ui <- navbarPage(
   title = "Popup Example",
   header = tags$head(tags$script(js)),
   tabsetPanel(
      id = "tabs",
      tabPanel(
         value = "tab1",
         title = "Tab 1",
      ),
      tabPanel(
         value = "tab2",
         title = "Tab 2",
         dataTableOutput("tbl")
      )
   ),
   id = "navbar"
)


server <- function(input, output, session) {
   output$tbl <- renderDataTable({
      dat <- my_data
      dat[2, "b"] <- make_popover(dat[2, "b"],
                                  "Dismissible popover",
                                  "And here's some amazing content. It's very engaging. Right?")
      datatable(
         dat,
         escape = FALSE)
   })
   
   observeEvent(input$tabs, {
      if (input$tabs == "tab2") {
         session$sendCustomMessage("show_popover", 1)
      }
   })
}

shinyApp(ui, server)

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Look for and choose various fields from a lengthy JSON object

I am working with a JSON object that contains a large list of offerValue objects. { "Code": 0, "response": "SUCCESS", "offerValue": [ { "id": "111", "name": "ABC", "flag": "V" }, { ...

Refreshing the current window with the ``Window.location.reload()`` function

I have integrated a map that displays clients using markers. The map I am utilizing is Leaflet with an AngularJS directive. The issue I am facing is that when I initially access the map, it functions correctly. However, when I change routes, all the marke ...

Title: "Uncovering Location Data in JSON Files"

I have been experimenting with the R programming language. Issue at Hand: I am attempting to replicate a map similar to this one using leaflet: (specifically for 2019). This is what I have tried so far: Step 1 : Initially, I downloaded the JSON file fo ...

Tips for personalizing and adjusting the color scheme of a menu in ant design

I am currently working on a website using reactJs and ant design. However, I have encountered an issue with changing the color of a menu item when it is selected or hovered over. Here's the current menu: Menu Image I would like to change the white col ...

What is the best way to expand the width of a table cell in a React + Material project?

Currently, I am utilizing material UI in conjunction with React to display my data in a table format. Within the table, there are specific titles such as "GENERAL_INFORMATION" and "INFORMATION" that I intend to center align. However, I have encountered an ...

applying multiple conditions to filter data in javascript

I have been working on filtering data based on input, and it is functioning well. However, I am looking to add an additional condition to the filter. I want it to return if either the title or another value (such as sendFrom) is provided. const newData = ...

Guide on extracting part of a string in JavaScript from a specific starting point to a designated character

Currently working on a JavaScript project where I am in need of extracting words enclosed within two brackets. For example: [Green]- Amazon I specifically require the word "Green" from within the brackets. Using indexOf() won't work as there could ...

`In Node.js, retry attempts resulted in an HTTP 504 status code.`

I have a scenario where my http server always returns a 504 status code: const express = require('express') const app = express() app.get('/', (req, res) => { console.log('I AM HERE'); res.status(504).send('N ...

Error in browser caused by JQuery JavaScript, not Dreamweaver

I need help creating a webpage that can extract and display recent earthquake data based on user input location on Google Maps. I have been using Dreamweaver to test my code, and everything functions perfectly when I use the live webpage feature within th ...

React Native's NativeBase checkbox component: Overlapping text causing the content to extend beyond the confines of the screen

I am having trouble getting the text inside a checkbox (using nativebase) to shrink. Does anyone know why this is happening? Do I need to add some flex properties? import React from "react" import {Box, Center, Checkbox, Heading, NativeBaseProv ...

Upon clicking the 'Add Image' button, TINYMCE dynamically incorporates an input

I am in search of creative solutions to address an issue I'm facing. Currently, I am utilizing TINYMCE to incorporate text into my webpage. However, I would like to enhance this functionality by having a feature that allows me to add an image along w ...

Navigate to the specified location using AJAX

When I update a comment using AJAX, I want to automatically scroll down to the updated comment: $("#aggiorna").click(function(){ var value = $("#id").val(); var dato = $("#comment_edit").val(); var dato1 = $("#user_id").val(); var dato2 = ...

How can getters in vuex be utilized uniquely?

After dedicating two weeks to studying Vuex, I find myself pondering the true significance and purpose of getters in the framework. I ran the following code snippet and everything seems to be functioning properly. this.$store.getters["app/url"] ...

Determine the smallest distance between two data sets, for every individual element in the second data set

My challenge involves working with two data frames, ev1 and ev2, which contain timestamps for different types of events collected across multiple tests. Each data frame includes columns for "test_id" and "timestamp". I am trying to determine the minimum di ...

Error: JSON parsing stopped due to unexpected end of file while attempting to parse data

After testing with other APIs successfully, I found that this particular one is not functioning as expected. const express = require("express"); const https = require("https"); const bodyParser = require("body-parser"); const ...

What is the best way to connect my data with my Backbone Views?

I have successfully set up my views to show test data, and now I want to implement asynchronous data loading to fetch real information. However, I'm a bit confused on the best method to achieve this. Should I manually create AJAX calls? Or maybe utili ...

Difficulty replicating 3 input fields using JavaScript

Combining the values of 3 input fields into 1 Displaying 'fname mnane lname' in the fullname input field. Then copying the fullname value into another input field called fullname2. Check out the code below for both HTML and JavaScript implemen ...

The @ViewChild in Angular 2 seems to be unable to detect the BaseChartDirective from the ng2-charts

I'm currently using ng2-charts v1.5.0 and I'm facing an issue with updating the chart data after a click event. Despite following suggestions from other sources, I am unable to get it to work properly. Here is a snippet of my code: <div styl ...

What is the best way to transform a UTC/GMT date and time into CST in Javascript? (CST specifically, not based on

Dealing with a tricky situation where backend data is always stored in UTC time while our front-end data is in CST. Unfortunately, I don't have access to the system handling this 'black box' conversion. Trying to replicate this setup in our ...

JavaScript Discord bot encounters an issue: .sendMessage function is not recognized

Currently, I am developing a bot and testing its messaging functionality using .sendMessage method. (I prefer the bot not to send messages upon receiving any input, hence avoiding the use of: bot.on("message", function(message) {}); However, I am encoun ...