2017-11-21 4 views
0

Ich habe mehrere Shiny-Anwendungen, die Diagramme mit dynamischer Breite/Höhe basierend auf der Fenstergröße generieren.Verwenden der Fenstergröße in Shiny Modul

Meine Absicht war immer alle Anwendungen in eine App zu kombinieren, um eine Kombination aus navbar verwenden, navlist, tabPanel und Module as specified here.

Ein Arbeits Beispiel ist unten angegeben, ohne Verwendung Module:

library(shiny) 
library(plotly) 

# ui.R file below 
ui <- shinyUI(fluidPage(

    tags$head(tags$script(' 
     var dimension = [0, 0]; 
     $(document).on("shiny:connected", function(e) { 
     dimension[0] = window.innerWidth; 
     dimension[1] = window.innerHeight; 
     Shiny.onInputChange("dimension", dimension); 
     }); 
     $(window).resize(function(e) { 
     dimension[0] = window.innerWidth; 
     dimension[1] = window.innerHeight; 
     Shiny.onInputChange("dimension", dimension); 
     }); 
     ')), 

    navlistPanel(  
    tabPanel("Dynamic Dimensions", 
      plotlyOutput("myPlot") 
    ) 
) 
) 
) 


# server.R file below 
server <- function(input, output) { 

    output$myPlot <- renderPlotly({ 
    plot_ly(midwest, x = ~percollege, color = ~state, type = "scatter", 
      width = (0.6 * as.numeric(input$dimension[1])), 
      height = (0.75 * as.numeric(input$dimension[2]))) 
    }) 

} 


# Typically I replace below with run.R file and launch the app in browser 
shinyApp(ui = ui, server = server) 

Aufgrund der großen Anzahl von App-Komponenten Ich kombiniere, ich habe die meisten meinen Code modularisiert. Das ist, wo ich Probleme habe, die Dimensionen Variable aufzurufen, selbst wenn ich es in der ns-Funktion umbrechen (es scheint, dass die Dimension ignoriert wird). Unten ist die Gesamtheit meines Codes, erfolglos konvertiert von der obigen funktionierenden App. Dies ist eigentlich tut Arbeit, aber die Breite aktualisiert wird nicht korrekt:

MyPlot Module:

myPlotUI <- function(id, label = "My Plot"){ 


    ns <- NS(id) 


    tags$head(tags$script(" 
         var dimension = [0, 0]; 
         $(document).on('shiny:connected', function(e) { 
         dimension[0] = window.innerWidth; 
         dimension[1] = window.innerHeight; 
         Shiny.onInputChange('dimension', dimension); 
         }); 
         $(window).resize(function(e) { 
         dimension[0] = window.innerWidth; 
         dimension[1] = window.innerHeight; 
         Shiny.onInputChange('dimension', dimension); 
         }); 
         ")) 

    tagList(
      plotlyOutput(ns("myPlot")) 
) 

} 




myPlot <- function(input, output, session){ 
    ns <- session$ns 

    output$myPlot <- renderPlotly({ 
    plot_ly(midwest, x = ~percollege, color = ~state, type = "scatter", 
      width = (0.6 * as.numeric(input$dimension[1])), 
      height = (0.75 * as.numeric(input$dimension[2]))) 
    }) 

} 

Server, UI und shinyApp:

server <- function(input, output, session){ 
    callModule(myPlot, "myPlot") 
} 

# ui.R file below 
ui <- shinyUI(fluidPage(

# I've tried putting the js code in this section of the UI. Didn't work... 

    navlistPanel(

    tabPanel("Dynamic Dimensions", 
      myPlotUI("myPlot") 
    ) 
) 
) 
) 

shinyApp(ui = ui, server = server) 

Irgendwelche Tipps, wie ich zugreifen die Fenstermaße innerhalb eines modularisierten Plotobjekts? Vielen Dank!

Antwort

1

Das Problem ist, dass Eingabewerte, auf die von Modulen zugegriffen wird, Namespaced sind, während die Eingabewerte, die von Shiny.onInputChange festgelegt werden, nicht sind.

So im myPlot Modul erhält input$dimensionmyPlot-dimension aber der Eingang ist eigentlich nur dimension.

Eine Lösung wäre der Namensraum-ID, um das Skript zu machen:

library(shiny) 
library(plotly) 

myPlotUI <- function(id, label = "My Plot") { 
    ns <- NS(id) 
    dimensionId <- ns("dimension") 

    tagList(
    tags$head(tags$script(sprintf(" 
     var dimensionId = '%s'; 
     var dimension = [0, 0]; 

     $(document).on('shiny:connected', function(e) { 
     dimension[0] = window.innerWidth; 
     dimension[1] = window.innerHeight; 
     Shiny.onInputChange(dimensionId, dimension); 
     }); 

     $(window).resize(function(e) { 
     dimension[0] = window.innerWidth; 
     dimension[1] = window.innerHeight; 
     Shiny.onInputChange(dimensionId, dimension); 
     }); 
    ", dimensionId))), 

    plotlyOutput(ns("myPlot")) 
) 
} 

myPlot <- function(input, output, session) { 
    ns <- session$ns 

    output$myPlot <- renderPlotly({ 
    plot_ly(midwest, x = ~percollege, color = ~state, type = "scatter", 
      width = (0.6 * as.numeric(input$dimension[1])), 
      height = (0.75 * as.numeric(input$dimension[2]))) 
    }) 

} 

server <- function(input, output, session){ 
    callModule(myPlot, "myPlot") 
} 

ui <- fluidPage(
    navlistPanel(
    tabPanel("Dynamic Dimensions", 
      myPlotUI("myPlot")) 
) 
) 

shinyApp(ui = ui, server = server) 

Eine andere Lösung, die mit einem Haftungsausschluss kommt: GEFAHR, ohne Papiere, Missbrauch anfälligen Feature! Sie können die Root-Sitzung von einem Modul über session$rootScope() abrufen. Ich würde nicht empfehlen, es sei denn, Sie müssen wirklich, aber nur zum ersten Mal.

library(shiny) 
library(plotly) 

myPlotUI <- function(id, label = "My Plot") { 
    ns <- NS(id) 

    tagList(
    tags$head(tags$script(" 
     var dimension = [0, 0]; 

     $(document).on('shiny:connected', function(e) { 
     dimension[0] = window.innerWidth; 
     dimension[1] = window.innerHeight; 
     Shiny.onInputChange('dimension', dimension); 
     }); 

     $(window).resize(function(e) { 
     dimension[0] = window.innerWidth; 
     dimension[1] = window.innerHeight; 
     Shiny.onInputChange('dimension', dimension); 
     }); 
    ")), 

    plotlyOutput(ns("myPlot")) 
) 
} 

myPlot <- function(input, output, session) { 
    ns <- session$ns 
    rootInput <- session$rootScope()$input 

    output$myPlot <- renderPlotly({ 
    plot_ly(midwest, x = ~percollege, color = ~state, type = "scatter", 
      width = (0.6 * as.numeric(rootInput$dimension[1])), 
      height = (0.75 * as.numeric(rootInput$dimension[2]))) 
    }) 

} 

server <- function(input, output, session){ 
    callModule(myPlot, "myPlot") 
} 

ui <- fluidPage(
    navlistPanel(
    tabPanel("Dynamic Dimensions", 
      myPlotUI("myPlot")) 
) 
) 

shinyApp(ui = ui, server = server) 
+0

Arbeiten, danke! –

Verwandte Themen