---
title: "Including shinyjs in different types of apps"
author: "Dean Attali"
date: "`r Sys.Date()`"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Including shinyjs in different types of apps}
  %\VignetteEngine{knitr::rmarkdown}
  %\usepackage[utf8]{inputenc}
---

```{r setup, echo = FALSE, message = FALSE}
knitr::opts_chunk$set(tidy = FALSE, comment = "#>")
```

# Including shinyjs in different types of apps

## Table of contents

- [Basic use of shinyjs](#usage-basic)
- [Using shinyjs in Shiny Dashboards](#usage-dashboard)
- [Using shinyjs with navbarPage layout](#usage-navbarpage)
- [Using shinyjs in interactive R Markdown documents](#usage-interactive)
- [Using shinyjs when the user interface is built using an HTML file](#usage-html)

<h2 id="usage-basic">Basic use of shinyjs</h2>

A typical Shiny app has a UI portion and a server portion. Before using most shinyjs functions, you need to call `useShinyjs()` in the app's UI. It's best to include it near the top as a convention.

Here is a minimal Shiny app that uses `shinyjs`:

```
library(shiny)
library(shinyjs)

ui <- fluidPage(
  useShinyjs(),  # Include shinyjs

  actionButton("button", "Click me"),
  textInput("text", "Text")
)

server <- function(input, output) {
  observeEvent(input$button, {
    toggle("text")  # toggle is a shinyjs function
  })
}

shinyApp(ui, server)
```

This is how most Shiny apps should initialize `shinyjs` - by calling `useShinyjs()` near the top of the UI.

However, if you use shinyjs in any of the following cases:

- In Shiny dashboards (built using the `shinydashboard` package)
- In Shiny apps that use a `navbarPage` layout
- In interactive Rmd documents
- In Shiny apps that manually build the user interface with an HTML file or template (instead of using Shiny's UI functions)

Then the following sections will show you how you to include shinyjs.

<h2 id="usage-dashboard">Using shinyjs in Shiny Dashboards</h2>

`shinydashboard` is an R package that lets you create nice dashboards with Shiny. Since it has a different structure than typical Shiny apps, it can be unclear where to include the call to `useShinyjs()` in these apps. It is recommended to place the call to `useShinyjs()` in the beginning of `dashboardBody()`. For example, here is a minimal Shiny dashboard that uses `shinyjs`:

```
library(shiny)
library(shinydashboard)
library(shinyjs)

ui <- dashboardPage(
  dashboardHeader(),
  dashboardSidebar(),
  dashboardBody(
    useShinyjs(),
    actionButton("button", "Click me"),
    div(id = "hello", "Hello!")
  )
)

server <- function(input, output) {
  observeEvent(input$button, {
    toggle("hello")
  })
}

shinyApp(ui, server)
```

<h2 id="usage-navbarpage">Using shinyjs with navbarPage layout</h2>

When creating a Shiny app that uses a `navbarPage` layout, the call to `useShinyjs()` can be placed inside any of the tabs (since the only real requirement is that it will be present *somewhere* in the UI). While having `useShinyjs()` inside the contents of any tab will work, there is another method that is preferred. You can wrap the `navbarPage` in a `tagList`, and call `useShinyjs()` within the `tagList`. This way, `shinyjs` gets set up in a way that is independent of each of the tabs. For example, here is a minimal Shiny app that uses `shinyjs` inside a `navbarPage` layout:

```
library(shiny)
library(shinyjs)

ui <- tagList(
  useShinyjs(),
  navbarPage(
    "shinyjs with navbarPage",
    tabPanel("tab1",
             actionButton("button", "Click me"),
             div(id = "hello", "Hello!")),
    tabPanel("tab2")
  )
)

server <- function(input, output, session) {
  observeEvent(input$button, {
    toggle("hello")
  })
}

shinyApp(ui, server)
```

<h2 id="usage-interactive">Using shinyjs in interactive R Markdown documents</h2>

It is possible to embed Shiny components in an R Markdown document, resulting in interactive R Markdown documents. More information on how to use these documents is available [on the R Markdown website](http://rmarkdown.rstudio.com/authoring_shiny.html). Even though interactive documents don't explicitly specify a UI and a server, using `shinyjs` is still easy: simply call `useShinyjs(rmd = TRUE)` (note the `rmd = TRUE` argument). For example, the following code can be used inside an R Markdown code chunk (assuming the document is set up as a Shiny document as the link above describes):

```
library(shinyjs)

useShinyjs(rmd = TRUE)
actionButton("button", "Click me")
div(id = "hello", "Hello!")

observeEvent(input$button, {
 toggle("hello")
})
```

<h2 id="usage-html">Using shinyjs when the user interface is built using an HTML file/template</h2>

While most Shiny apps use Shiny's functions to build a user interface to the app, it is possible to build the UI with an HTML template, [as RStudio shows in this article](http://shiny.rstudio.com/articles/templates.html). In this case, you simply need to add `{{ useShinyjs() }}` somewhere in the template, preferably inside the `<head>...</head>` tags.

A similar way to create your app's UI with HTML is to write it entirely in HTML (without templates), [as RStudio shows in this article](http://shiny.rstudio.com/articles/html-ui.html). Building Shiny apps like this is much more complicated and should only be used if you're very comfortable with HTML. Using `shinyjs` in these apps is possible but it works a little differently since there is no `ui.R` to call `useShinyjs()` from.  There are three simple steps to take in order to use `shinyjs` in these apps:

- create a `global.R` file in the same directory as your `server.R`, and add the following line to the file:

        shiny::addResourcePath("shinyjs", system.file("srcjs", package = "shinyjs"))
        
- in the `index.html` file you need to load a special JavaScript file named `shinyjs/inject.js`. You do this by adding the following line to the HTML's `<head>` tag:

        `<script src="shinyjs/inject.js"></script>`
        
- in your server function (the `shinyServer` function) you need to call `useShinyjs(html = TRUE)`

After adding these three lines to your code, you can use all `shinyjs` functions as usual.
