Combining R and JavaScript: How to Use JavaScript in R Shiny

Estimated time:
time
min

It's no secret that we love R Shiny and everything it has to offer. But the harsh truth is that other programming languages, such as JavaScript, give you more options when it comes to interactive data visualizations. Now, that's not because JavaScript is better than R. It simply has a larger user base, which leads to more open-source and commercial projects. But what if you could bridge the gap somehow? What if you could combine JavaScript with R and R Shiny? It turns out it's possible, and the entire integration is mostly straightforward. After reading this article, you'll know how to use R Shiny JavaScript packages to combine the best of both worlds. We'll give you plenty of reasons why it might be a good idea, and provide two hands-on examples of porting JavaScript code into R Shiny. Let's dive in! <blockquote>Are you new to R? <a href="https://appsilon.com/r-for-programmers/" target="_blank" rel="noopener">Here are 7 essential R packages you must know about</a>.</blockquote> Table of contents: <ul><li><a href="#intro">R Shiny and JavaScript - Why is it a Good Idea</a></li><li><a href="#how">R Shiny JavaScript - How to Get Started</a></li><li><a href="#example-1">Example 1: Interactive Leaflet Map in R Shiny JavaScript</a></li><li><a href="#example-2">Example 2: Calendar in R Shiny JavaScript with D3</a></li><li><a href="#conclusion">Summing up R Shiny JavaScript</a></li></ul> <hr /> <h2 id="intro">JavaScript in R Shiny - Why is it a Good Idea</h2> As we mentioned briefly in the introduction section, JavaScript simply has more options if you care about interactive visualizations. There are other reasons why combining R Shiny JavaScript is a good idea. Here's a brief description for five of these reasons: <ol><li><b>Ecosystem Integration:</b> JavaScript is primarily used in modern web development, and many popular tools and frameworks integrate seamlessly with it. By leveraging JavaScript in your R and R Shiny applications, you can tap into the broader web development ecosystem, collaborate with front-end developers, and benefit from the wealth of shared knowledge and resources available.</li><li><b>More Data Visualization Options:</b> JavaScript libraries like D3.js, Plotly.js, and Highcharts.js provide powerful and flexible data visualization capabilities. By integrating JavaScript with R and R Shiny, you can leverage these libraries to create stunning and interactive charts, graphs, and visualizations.</li><li><b>Advanced User Interactions: </b>JavaScript allows you to create complex user interactions that go beyond the capabilities of standard HTML and CSS. You can build interactive forms, drag-and-drop functionality, sliders, modals, and more to provide a rich and engaging user experience. Most of these functionalities are already built into R Shiny, but JS provides another layer of options and customization.</li><li><b>Asynchronous Programming: </b>JavaScript's event-driven and non-blocking nature is particularly useful when dealing with asynchronous tasks such as fetching data from APIs or performing background computations. Integrating JavaScript in R and R Shiny allows you to handle these tasks efficiently.</li><li><b>No code duplication:</b> If you already have a functioning JavaScript code, why bother looking for an alternative R package? R Shiny JavaScript integration allows you to reuse the same programming logic.</li></ol> These alone should leave you convinced, so now let's dive into the practical stuff! <h2 id="how">R Shiny JavaScript - How to Get Started</h2> First things first, how do you actually get started integrating JavaScript into R Shiny applications? Well, you'll have to install the <code>shinyjs</code> package. You can do so by running the following command from the R console: <pre><code class="langaage-bash">install.packages("shinyjs")</code></pre> Once the package is installed, everything boils down to calling the <code>useShinyjs()</code> function in the Shiny app's UI, and then run the <code>runjs()</code> function in the Shiny app's server. Here's a sample application that has a single button that shows an alert message when clicked. If you know the basic of JavaScript, you know what the <code>alert()</code> function does: <pre><code class="language-r">library(shiny) library(shinyjs) <br>ui &lt;- fluidPage(  useShinyjs(),  actionButton(inputId = "executeButton", label = "Execute JavaScript") ) <br>server &lt;- function(input, output) {    observeEvent(input$executeButton, {    # JavaScript code to be executed    js_code &lt;- "alert('JavaScript code executed!');"    runjs(js_code)  })   } <br>shinyApp(ui, server)</code></pre> This is what you will see after running the app: <img class="size-full wp-image-19822" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7d720bc9849746c770403_0f8f2edb_1.webp" alt="Image 1 - Using JavaScript in R Shiny (1)" width="1255" height="1069" /> Image 1 - Using JavaScript in R Shiny (1) Once you click on the button, you'll see the alert message: <img class="size-full wp-image-19824" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7d72034291e95149d357b_9ab528c9_2.webp" alt="Image 2 - Using JavaScript in R Shiny (2)" width="1255" height="1069" /> Image 2 - Using JavaScript in R Shiny (2) And that's how easy it is to combine JavaScript and R Shiny. Let's now dive into two slightly more complex examples: <h2 id="example-1">Example 1: Interactive Leaflet Map in R Shiny JavaScript</h2> Leaflet is an amazing library for showing and manipulating maps. It offers plenty of customization options, from the overall map aesthetics to adding custom overlays and markers. We'll start this section by implementing a Leaflet map in pure JavaScript, and then see how to make a transition to R Shiny. <h3>Coding the Leaflet Map in JavaScript</h3> Leaflet in JavaScript requires you to import their CSS and JS files. It's a pre-written logic and style code that's ready for you to use. After the import, we'll declare a custom CSS block for the map styles (just tweaking width and height). The <code>body</code> of our site will contain a blank <code>div</code> element that's connected in the <code>script</code> tag. This last part essentially creates a Leaflet map, tweaks the aesthetics, and adds a marker in Warsaw's iconic <i>Zamek Królewski w Warszawie</i>, or <i>The Royal Caste in Warsaw</i> if it's too early in the morning for Polish pronunciation for you: <pre><code class="language-html">&lt;!DOCTYPE html&gt; &lt;html lang="en"&gt; &lt;head&gt;  &lt;meta charset="UTF-8"&gt;  &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;  &lt;title&gt;Leaflet&lt;/title&gt; <br>  &lt;!- Load Leaflet CSS file -&gt;  &lt;link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"     integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY="     crossorigin=""/&gt;  &lt;!- Load Leaflet JS file -&gt;  &lt;script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"     integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo="     crossorigin=""&gt;&lt;/script&gt; <br>  &lt;!- Basic CSS for the map -&gt;  &lt;style&gt;    #map {      width: 1024px;      height: 768px;    }  &lt;/style&gt; <br>&lt;/head&gt; &lt;body&gt;    &lt;!- Blank container for the map -&gt;    &lt;div id="map"&gt;&lt;/div&gt; <br>    &lt;script&gt;      // Initialize map and set location      let map = L.map("map").setView([52.237049, 21.017532], 12);            // Tile layer configuration      L.tileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png", {          attribution: '© &lt;a href="https://www.openstreetmap.org/copyright"&gt;OpenStreetMap&lt;/a&gt; contributors'      }).addTo(map); <br>      // Add a point of interest to the map      L.marker([52.2377309, 21.0206092]).addTo(map)        .bindPopup("Zamek Królewski w Warszawie")        .openPopup();    &lt;/script&gt; &lt;/body&gt; &lt;/html&gt;</code></pre> You can save the above code to an HTML file. For reference, we've saved ours to <code>index.html</code> file and then opened it. Here are the results: <img class="size-full wp-image-19826" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7d721f3c71ae17692ff4e_209c1142_3.webp" alt="Image 3 - Leaflet JS map" width="1859" height="1487" /> Image 3 - Leaflet JS map That's the map logic for you. Let's now bring it to R Shiny. <h3>Embedding a JavaScript Leaflet Map in R Shiny</h3> Just like with the pure JavaScript implementation, we need a way to bring Leaflet's JS and CSS files into R Shiny. Luckily, you can call <code>tags$link()</code> and <code>tags$script()</code> inside <code>tags$head()</code> to embed these. The story is similar for custom CSS styles. To render a <code>div</code> with an <code>id</code> property in R Shiny, you need to call the <code>uiOutput(outputId = "id")</code> function. Then, inside the <code>server()</code> function, you can essentially copy the entire JavaScript code from the previous section and surround it with <code>tags$script(HTML())</code> as a string. Keep in mind that you'll have to escape nested double quotes in the code - the thing won't work otherwise. Here's the entire <code>app.R</code> content: <pre><code class="language-r">library(shiny) library(shinyjs) ui &lt;- fluidPage(  # Specify to use Shiny JS  useShinyjs(),  # Load Leaflet CSS and JS  tags$head(    tags$link(rel = "stylesheet", type = "text/css", href = "https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"),    tags$script(src = "https://unpkg.com/leaflet@1.9.4/dist/leaflet.js")  ),  # Custom CSS  tags$style(HTML("    #map {      width: 1024px;      height: 768px;    };  ")),  # Map container  uiOutput(outputId = "map") ) server &lt;- function(input, output, session) {  output$map &lt;- renderUI({    tags$script(HTML('      // Initialize map and set location      let map = L.map("map").setView([52.237049, 21.017532], 12);      // Tile layer configuration      // Do not forget to escape the quotation marks around the URL!      L.tileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png", {          attribution: "© &lt;a href=\\https://www.openstreetmap.org/copyright\\"&gt;OpenStreetMap&lt;/a&gt;&gt;contributors""

Contact us!
Damian's Avatar
Damian Rodziewicz
Head of Sales
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
nan