Friday, 28 October 2022

Shiny renderUI does not show different D3 Plots after Changing the Tab in TabsetPanel

What I want to do

I am trying to build a shiny app, that shows different interactive HTML-plots using a tabset panel. They all should show up in the same call of renderUI. As shown below in my example, my plots are based on the d3 framework (as in the packages networkD3 andprocessanimateR).

The Problem

Unfortunately, only the first plot that is generated is shown by renderUI. Once the tab is changed, the second plot does not show up. processanimateR gives me the error Failed to render the graph. It is probably too large. Original error: TypeError: d3.create is not a function at PATokens.insertTokens (<anonymous>:185:25) at <anonymous>:52:33 at <anonymous>:105:9. Of course, the plot is not too large to be shown (data-wise), as changing the tab-sequence generates it perfectly. This behavior is independent of which plot shows first. In the example below, I marked the lines you can use to swap tab01 and tab02 to see what happens.

What I tried

By coming up with the smallest example I could, I possibly ruled out a lot of sources for error. Additionally, I have tried using multiple uiOutput (one per tab) without success. The problem persists. As this minimal example suggests, it might be a problem with d3 running in the background. Maybe there's some graphical engine that doesn't close on tab-change or something else js related.

My question

Is there a way to show multiple d3 plots in a shiny app, making them all show up as intended?

Thank you in advance!

My example

#XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
# Settings
#XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
# Packages
sapply(c("shiny","processanimateR","bupaR","networkD3"),require,character.only=T)

# data
x <- structure(list(
    activity = c(
        "action 1", "action 2", "action 3", 
        "action 5", "action 2", "action 3", "action 25", "action 26", 
        "action 2", "action 3", "action 1", "action 2", "action 3", "action 1", 
        "action 2", "action 3", "action 1", "action 2", "action 3", "action 5", 
        "action 2", "action 3", "action 25", "action 26", "action 2", 
        "action 3", "action 1", "action 2", "action 3", "action 1", "action 2", 
        "action 3"),
    id = c(494.18, 494.18, 494.18, 485.56, 485.56, 485.56, 
           413.99, 413.99, 413.99, 413.99, 439.49, 439.49, 439.49, 466.38, 
           466.38, 466.38, 494.18, 494.18, 494.18, 485.56, 485.56, 485.56, 
           413.99, 413.99, 413.99, 413.99, 439.49, 439.49, 439.49, 466.38, 
           466.38, 466.38), .order = 1:32,
    activity_instance_id_by_bupar = c(1L, 
                                      2L, 3L, 16L, 17L, 18L, 50L, 51L, 52L, 53L, 60L, 61L, 62L, 71L, 
                                      72L, 73L, 1L, 2L, 3L, 16L, 17L, 18L, 50L, 51L, 52L, 53L, 60L, 
                                      61L, 62L, 71L, 72L, 73L),
    lifecycle_id = c("start", "start", 
                     "start", "start", "start", "start", "start", "start", "start", 
                     "start", "start", "start", "start", "start", "start", "start", 
                     "complete", "complete", "complete", "complete", "complete", "complete", 
                     "complete", "complete", "complete", "complete", "complete", "complete", 
                     "complete", "complete", "complete", "complete"),
    timestamp = structure(c(1424304001, 
                            1377475201, 1516579201, 1384128001, 1375401601, 1397952001, 1328486401, 
                            1364688001, 1318032001, 1384905601, 1348099201, 1342483201, 1366416001, 
                            1361404801, 1358726401, 1384905601, 1425168001, 1378339201, 1517443201, 
                            1384992001, 1376265601, 1398816001, 1329350401, 1365552001, 1318896001, 
                            1385769601, 1348963201, 1343347201, 1367280001, 1362268801, 1359590401, 
                            1385769601),
                          tzone = "UTC", class = c("POSIXct", "POSIXt")), 
    trace = c("action 2,action 1,action 3", "action 2,action 1,action 3", 
              "action 2,action 1,action 3", "action 2,action 5,action 3", 
              "action 2,action 5,action 3", "action 2,action 5,action 3", 
              "action 2,action 25,action 26,action 3", "action 2,action 25,action 26,action 3", 
              "action 2,action 25,action 26,action 3", "action 2,action 25,action 26,action 3", 
              "action 2,action 1,action 3", "action 2,action 1,action 3", 
              "action 2,action 1,action 3", "action 2,action 1,action 3", 
              "action 2,action 1,action 3", "action 2,action 1,action 3", 
              "action 2,action 1,action 3", "action 2,action 1,action 3", 
              "action 2,action 1,action 3", "action 2,action 5,action 3", 
              "action 2,action 5,action 3", "action 2,action 5,action 3", 
              "action 2,action 25,action 26,action 3", "action 2,action 25,action 26,action 3", 
              "action 2,action 25,action 26,action 3", "action 2,action 25,action 26,action 3", 
              "action 2,action 1,action 3", "action 2,action 1,action 3", 
              "action 2,action 1,action 3", "action 2,action 1,action 3", 
              "action 2,action 1,action 3", "action 2,action 1,action 3"
    ),
    n = c(3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 3, 3, 3, 3, 3, 
          3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3),
    absolute_frequency = c(3L, 
                           3L, 3L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 3L, 3L, 3L, 3L, 3L, 3L, 
                           3L, 3L, 3L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 3L, 3L, 3L, 3L, 3L, 
                           3L),
    relative_frequency = c(0.272727272727273, 0.272727272727273, 
                           0.272727272727273, 0.0909090909090909, 0.0909090909090909, 
                           0.0909090909090909, 0.0909090909090909, 0.0909090909090909, 
                           0.0909090909090909, 0.0909090909090909, 0.272727272727273, 
                           0.272727272727273, 0.272727272727273, 0.272727272727273, 
                           0.272727272727273, 0.272727272727273, 0.272727272727273, 
                           0.272727272727273, 0.272727272727273, 0.0909090909090909, 
                           0.0909090909090909, 0.0909090909090909, 0.0909090909090909, 
                           0.0909090909090909, 0.0909090909090909, 0.0909090909090909, 
                           0.272727272727273, 0.272727272727273, 0.272727272727273, 
                           0.272727272727273, 0.272727272727273, 0.272727272727273)),
    row.names = c(NA, 
                  -32L),
    class = c("eventlog", "log", "tbl_df", "tbl", "data.frame"
    ),
    case_id = "id", activity_id = "activity", activity_instance_id = "activity_instance_id_by_bupar",
    lifecycle_id = "lifecycle_id",
    resource_id = "id",
    timestamp = "timestamp")
y <- jsonlite::fromJSON(paste0('https://cdn.rawgit.com/christophergandrud/networkD3/','master/JSONdata/energy.json'))

#XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
# Shiny-App UI ----
#XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
ui <- shinyUI(fluidPage(
    title="shiny example",
    sidebarLayout(
        position="left",
        sidebarPanel(),
        mainPanel(
            tags$div(
                do.call(
                    tabsetPanel,
                    c(id='tabs',
                      lapply(1:2,function(y){
                          tabPanel(id=paste0("tab0",y),value=paste0("tab0",y),title=strong(paste0("This is tab0",y),align="left",style="black"),selected=1)
                      })
                    )
                ),
                uiOutput("out_ui")
            )
        )
    ),
    style=paste0("font-family: Arial;")
))

#XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
# Shiny-App Server ----
#XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
server <- function(input,output,session){
    output$out_ui <- renderUI({
        
        # X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X
        # >>>> Problem Segment <<<< ----
        # X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X
        # Try: Chance this to "tab01"
        if(input$tabs=="tab02"){
            
            # Process
            animate_process(
                x,
                processmap=process_map(
                    x,
                    type=frequency("absolute",color_scale="Paired",color_edges="Greys"),
                    rankdir="TB",render=F,fixed_edge_with=T,
                    layout=layout_pm(
                        edge_weight=F,
                        edge_cutoff=0)),
                mapping=token_aes(
                    size=token_scale(8),
                    color=token_scale(
                        range="black",
                        scale="ordinal"
                    ),
                    opacity=token_scale(100)
                ),
                duration=60,mode="absolute",timeline=T,jitter=10,initial_time=0,
                repeat_count=10,repeat_delay=2,width=1200,height=900,
                sizingPolicy=htmlwidgets::sizingPolicy(
                    browser.fill=T,viewer.fill=F,
                    knitr.figure=F,knitr.defaultWidth="100%",knitr.defaultHeight="1000")
            )
            
        # X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X
        # >>>> Problem Segment <<<< ----
        # X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X
        # Try: Chance this to "tab02"
        }else if(input$tabs=="tab01"){
            
            # Sankey
            sankeyNetwork(
                Links=y$links,Nodes=y$nodes,Source='source',
                Target='target',Value='value',NodeID='name',
                units='TWh',fontSize=12,nodeWidth=30
            )
        }
    })
}
shinyApp(ui=ui,server=server)

#XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX


from Shiny renderUI does not show different D3 Plots after Changing the Tab in TabsetPanel

No comments:

Post a Comment