TransWikia.com

R Shiny HTML object is rendered on every tabPanel()

Stack Overflow Asked by Ju Ko on December 20, 2021

I am trying to create a shiny app where users can upload their own data and get a visualization of the network dynamics in their data. I’m using the render.d3movie() function from the ndtv package to create an HTML object from the network with some user input parameters. I want to display this HTML object in one of my tabPanel()s but weirdly, it shows up on every panel instead. I tried with a different HTML file and this one works just fine. To reproduce this, you’ll need to download the test and network animation html files and put them in the same directory as the example shiny app code below.

Example:

library(shiny)

# Define UI for application that draws a histogram
ui <- fluidPage(

    navbarPage("ShinyExample",
        
        tabPanel("TEST", HTML("FirstPage"), includeHTML("test.html")),
        
        tabPanel("TEST2", HTML("SecondPage"), includeHTML("NetworkAnimation.html"))
  
    )

)

# Define server logic required to draw a histogram
server <- function(input, output) {

    # Stuff to render and save the network Animation happens here

}

# Run the application 
shinyApp(ui = ui, server = server)

Expected Behavior:

test.html and NetworkAnimation.html should only be rendered within their respective tabPanel()

Observed Behavior:

test.html is only rendered in it’s respective tabPanel() but NetworkAnimation.html is rendered on both tabPanel() s

One Answer

The network-widget is appended to the body in the NetworkAnimation.html-Javascript:
target = d3.select('body').append('div').style({width: '100%', height: '100%'}).node();.

If you want it to be on Tab 2 only, you can include a div with id and change the JavaScript line, so that it gets appended to your div.

My App looks like this:

ui <- fluidPage(
  ## Include shinyjs
  useShinyjs(),
  ## Set ID of navbarPage
  navbarPage("ShinyExample", id = "navid",
             tabPanel("TEST", includeHTML("test.html")),
             tabPanel("TEST2",
                      ## Include new DIV here & Set initial height
                      div(id="appendhere", style="height: 1090px;"), 
                      includeHTML("NetworkAnimation.html"))
  )
)
server <- function(input, output) {
    observe({
        req(input$navid == "TEST2")
        runjs('$("#appendhere").resize()')
    })
}

# Run the application
shinyApp(ui = ui, server = server)

and the JS is changed to

target = d3.select('#appendhere').append('div').style({width: '100%', height: '100%'}).node();

I also had to include shinyjs, to run some JavaScript when TAB2 is active. The width/height of the svg is calculated when it is rendered and therefore initially 0 (or actually -60). If you remove the runjs line, you will see that the network is not visible.

By changing the browser size, the network gets redrawn and width/height are updated. Therefore we call $("#appendhere").resize() when TAB2 is active.

There is still the following error in the browser console, but everything seems to work fine.

Uncaught TypeError: a is undefined

Answered by SeGa on December 20, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP