Search code examples
rshinynvd3.jsrchartsggvis

Add Interactive Chart to Shiny with HTML UI (index.html)


I can see how ggvis, rCharts, etc. fits in with a server.r + ui.r construction. I'm now trying to make an HTML UI but am and unable to find any clues about passing an interactive chart to an HTML UI. Any clues?

Investigated for ggvis, rCharts, NBD3. Not investigated for plotly. Avoiding googleVis.

A similar question has been asked before, by an Evan Farrell, but with no response - https://groups.google.com/forum/#!topic/ggvis/GsZQRl3VOZ4

Edit: Do these need custom binding? Any simpler alternatives? I thought the output would be javascript produced SVG, so is it not possible for the libraries to be included manually and the SVG just bound to a div element?

Edit 2: Could I pass my dataset to the UI somehow and build say a D3 chart in index.html itself


Solution

  • You can find here examples such as which is shiny with ggvis:

    library(shiny)
    library(ggvis)
    
    runApp(list(
    
      ui={
        library(ggvis)
        shinyUI(pageWithSidebar(
          div(),
          sidebarPanel(
            sliderInput("n", "Number of points", min = 1, max = nrow(mtcars),
                        value = 10, step = 1),
            uiOutput("plot_ui")
          ),
          mainPanel(
            htmlOutput("ggvis_plot"),
            tableOutput("mtc_table")
          )
        ))
    
      },
    
      server={
        library(ggvis)
        shinyServer(function(input, output, session) {
    
          output$ggvis_plot <- renderUI({
            ggvisOutput("plot1")
          })
          # A reactive subset of mtcars
          mtc <- reactive({ mtcars[1:input$n, ] })
          # A simple visualisation. In shiny apps, need to register observers
          # and tell shiny where to put the controls
          mtc %>%
            ggvis(~wt, ~mpg) %>%
            layer_points() %>%
            bind_shiny("plot1")
          output$mtc_table <- renderTable({
            mtc()[, c("wt", "mpg")]
          })
        })
      }
    ))
    

    To convert it to a html-UI, shiny project you would need to create a directory with the following structure (as described here, as pointed by hvollmeier):

    <shinnyappName>
    |-- www
         |-- index.html
    |-- server.R
    

    The server part will remain the same. For our example the index.html part would be something like:

    <!DOCTYPE html>
    <html>
    <head>
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
      <script type="application/shiny-singletons"></script>
      <script type="application/html-dependencies">json2[2014.02.04];jquery[1.11.0];shiny[0.11.1];ionrangeslider[2.0.2];bootstrap[3.3.1]</script>
    <script src="shared/json2-min.js"></script>
    <script src="shared/jquery.min.js"></script>
    <link href="shared/shiny.css" rel="stylesheet" />
    <script src="shared/shiny.min.js"></script>
    <link href="shared/ionrangeslider/css/normalize.css" rel="stylesheet" />
    <link href="shared/ionrangeslider/css/ion.rangeSlider.css" rel="stylesheet" />
    <link href="shared/ionrangeslider/css/ion.rangeSlider.skinShiny.css" rel="stylesheet" />
    <script src="shared/ionrangeslider/js/ion.rangeSlider.min.js"></script>
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link href="shared/bootstrap/css/bootstrap.min.css" rel="stylesheet" />
    <script src="shared/bootstrap/js/bootstrap.min.js"></script>
    <script src="shared/bootstrap/shim/html5shiv.min.js"></script>
    <script src="shared/bootstrap/shim/respond.min.js"></script>
    
    </head>
    <body>
      <div class="container-fluid">
        <div class="row">
          <div></div>
        </div>
        <div class="row">
          <div class="col-sm-4">
            <form class="well">
              <div class="form-group shiny-input-container">
                <label class="control-label" for="n">Number of points</label>
                <input class="js-range-slider" id="n" data-min="1" data-max="32" data-from="10" data-step="1" data-grid="true" data-grid-num="7.75" data-grid-snap="false" data-prettify-separator="," data-keyboard="true" data-keyboard-step="3.2258064516129"/>
              </div>
              <div id="plot_ui" class="shiny-html-output"></div>
            </form>
          </div>
          <div class="col-sm-8">
            <div id="ggvis_plot" class="shiny-html-output"></div>
            <div id="mtc_table" class="shiny-html-output"></div>
          </div>
        </div>
      </div>
    </body>
    </html>
    

    Which you should write or you could get if you save the html page generated by the shinyUI as index.html and modify it to your needs as well as remove anything extra and undesirable.

     library(shiny)
     runApp("<shinyAppName>")