Easily Improve the User Experience of Your Shiny Apps in Seconds

Perform common useful JavaScript operations in Shiny apps that will greatly improve your apps without having to know any JavaScript. Examples include: hiding an element, disabling an input, resetting an input back to its original value, delaying code execution by a few seconds, and many more useful functions for both the end user and the developer. 'shinyjs' can also be used to easily call your own custom JavaScript functions from R.



Easily improve the user experience of your Shiny apps in seconds

Official website ยท Copyright 2016 Dean Attali

Donate Build Status CRAN version

shinyjs lets you perform common useful JavaScript operations in Shiny apps that will greatly improve your apps without having to know any JavaScript.

Examples include: hiding an element, disabling an input, resetting an input back to its original value, delaying code execution by a few seconds, and many more useful functions for both the end user and the developer. shinyjs can also be used to easily call your own custom JavaScript functions from R.

shinyjs is under the AGPL-3 license. For a commercial license, please contact me. If you find shinyjs useful, please consider supporting its development!

Demos and tutorials

Overview of main functions

Note: In order to use any shinyjs function in a Shiny app, you must first call useShinyjs() anywhere in the app's UI.

Function Description
show/hide/toggle Display or hide an element (optionally with an animation).
hidden Initialize a Shiny tag as invisible (can be shown later with a call to show).
enable/disable/toggleState Enable or disable an input element, such as a button or a text input.
disabled Initialize a Shiny input as disabled.
reset Reset a Shiny input widget back to its original value.
delay Execute R code (including any shinyjs functions) after a specified amount of time.
alert Show a message to the
click Simulate a click on a button
html Change the text/HTML of an element.
onclick Run R code when a specific element is clicked. Was originally developed with the sole purpose of running a shinyjs function when an element is clicked, though any R code can be used.
onevent Similar to onclick, but can be used with many other events instead of click (for example, listen for a key press, mouse hover, etc).
addClass/removeClass/toggleClass add or remove a CSS class from an element.
runjs Run arbitrary JavaScript code.
extendShinyjs Allows you to write your own JavaScript functions and use shinyjs to call them as if they were regular R code. More information is available in the section "Calling your own JavaScript functions from R" below.

Functions that help you during Shiny app development

Function Description
runcodeUI+runcodeServer Adds a text input to your app that lets you run arbitrary R code live.
showLog Print any JavaScript console.log() messages in the R console, to make it easier and quicker to debug apps without having to open the JS console.
logjs Print a message to the JavaScript console (mainly used for debugging purposes).
inlineCSS Easily add inline CSS to a Shiny app.

Check out the shinyjs demo app to see some of these in action, or install shinyjs and run shinyjs::runExample() to see more demos.


To install the stable CRAN version:


To install the latest development version from GitHub:


How to use

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:


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 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 you should see the Including shinyjs in different types of apps document.

If your Shiny app doesn't fall into any of these categories, then the above code sample should be enough to get your started with including shinyjs in your app.

Basic use case - complete working example

See the shinyjs example app walk-through document for a step-by-step guide on how to add a variety of shinyjs features to a simple app in order to make it more user friendly.

Calling your own JavaScript functions from R

You can also use shinyjs to add your own JavaScript functions that can be called from R as if they were regular R functions using extendShinyjs. This is only suitable for advanced users who are familiar with JavaScript and wish to facilitate the communication between R and JavaScript.

To learn about this feature and see how useful it can be, see the extendShinyjs: Calling your own JavaScript functions from R document.

FAQ and extra tricks

There are several questions that pop up very frequently in my email or on StackOverflow about "How do I use shinyjs to do ___?" Here is a list of a few of these common questions with links to a solution that could be useful. Note that all of these require using extendShinyjs().

I also keep a long list of various Shiny tips & tricks for solving common Shiny problems, many of which make use of shinyjs.

More resources

This document is meant to serve as a high overview of shinyjs. There are three more documents provided in shinyjs to teach you various aspects of the package:

If you need help with shinyjs, a good place to start is to try to get help from the community. I suggest browsing the shinyjs tag on StackOverflow or asking your own question there. You can also try getting help on the RStudio Community forums.

If you still can't get an answer to your question, you can contact me. However, because of the high volume of support emails I receive daily, I can only provide support for a fee (as part of my Shiny consulting).

Motivation & alternatives using native Shiny

The initial release of this package was announced on my blog and discusses these topics.


If you have any suggestions or feedback, I would love to hear about it. You can either message me directly, open an issue if you want to request a feature/report a bug, or make a pull request if you can contribute.

I'd like to give special thanks to the Shiny developers, especially Joe Cheng for always answering all my Shiny questions.

Lastly, if you find shinyjs useful, please consider supporting me for the countless hours I've spent building, documenting, and supporting this package :)


shinyjs 1.0


  • BREAKING CHANGE shiny version 1.0.0 is now required
  • BREAKING CHANGE All colourInput-related functions are now defunct because they are now in the colourpicker package
  • Added click() function that simulates a user clicking on a button
  • Bug fix: reset() wasn't working on checkboxes/select inputs that had a comma in the value (#130)
  • Bug fix: using disabled() on certain non-standard inputs (such as shinyFiles) had strange behaviour (#120)
  • Bug fix: logjs()+showLog() wasn't working when app first runs
  • Bug fix: reset() wasn't working on file inputs with an ID that contained a dot (#140)
  • Moved default values of parameters to the R layer instead of being defined in javascript. This means that RStudio no longer complains of missing arguments and that autocompletion will show default values. (#80)
  • Improve efficiency of delay() and reset() functions
  • Improve documentation and website (https://deanattali.com/shinyjs)

shinyjs 0.9


  • added support for shinyAce editor as the input for runcodeUI() (#93)
  • showLog() no longer needs to be specified in useShinyjs(), and it can be used by just calling it in the server code once (#105)
  • fixed bug where showLog() would only show the last message if multiple messages were printed in succession (#99)
  • fixed bug where date inputs could not be reset to empty (#100)
  • fixed textArea inputs not getting disabled when disabling a parent element
  • add showElement()/hideElement()/toggleElement() and addCssClass etc functions as synonyms for functions that are masked by S4 (compromise for #81)
  • fixed broken runExample("sandbox") example
  • added a website for shinyjs: http://deanattali.com/shinyjs

shinyjs 0.8


  • added runcodeUI() and runcodeServer() functions that you can add to your app in order to run arbitrary R code interactively
  • added showLog() function which lets you redirect all JavaScript logging statements to the R console, to make it easier and quicker to debug apps without having to open the JS console (#88)
  • onclick and onevent now support callback functions, and the JavaScript Event object is passed to the callback (#92)
  • the reset() function now works on file inputs
  • added alert() as an alias for info()

shinyjs 0.7


  • All the colourpicker/colourInput related functions are now deprecated because I've made a more appropriate package for them colourpicker
  • Use updated colourpicker JS library that fixes bugs with new jquery version
  • Add reset support for passwordInput and textAreaInput (#78)

shinyjs 0.6.2


  • Improved UI of demo shiny apps and added social media meta tags and github fork ribbons

shinyjs 0.6.1


  • Added selector argument to html() function

shinyjs 0.6


  • info() function: don't include surrounding quotations if not necessary (#59)
  • added documentation for how to use shinyjs in HTML templates

shinyjs 0.5.3


  • Fixed bug with extendShinyjs() where it didn't work when using a script and didn't have V8 installed (#64)

shinyjs 0.5.2


  • Added numCols parameter to the colourPicker() gadget

shinyjs 0.5.1


  • Added returnName parameter to colourInput(), which lets you get an R colour name instead of HEX value as the return value (#62)

shinyjs 0.5.0


  • Added an awesome colour picker gadget and addin. Use colourPicker() to open a gadget that lets you pick colours, or choose Colour Picker from the Addins menu to run it.

shinyjs 0.4.1


  • html() function: don't attempt to change innerHTML if the element does not exist

shinyjs 0.4.0


  • BREAKING CHANGE: the text function has been renamed to html (#42)

  • shinyjs now works with the new modules feature of Shiny (#50)

  • Refactor how shinyjs R engine works: instead of using cool meta programming that minimizes code and sends each shinyjs function request straight to JS, add a thin layer or R code for each function. This allows us to check the arguments, run custom code for each function, it allows the documentation to show the arguments instead of them being ..., and it fixes a few edge cases of calling shinyjs functions, such as calling shinyjs using do.call() (#51)

  • Update vignette/readme to include FAQ

  • Change internally the name of shinyjs functions to make the JavaScript function names more unique to avoid potential conflicts with user-defined JS functions

shinyjs 0.3.2


  • Show warning when using Shiny modules because they aren't supported yet

shinyjs 0.3.0


  • bug fix: hidden() now works when used on an element with a display CSS property

shinyjs 0.2.6


  • bug fix: show/hide always trigger shown/hidden events

shinyjs 0.2.5


  • small UI change to colourInput demo shiny app

shinyjs 0.2.4


  • Support extendShinyjs() for users that cannot install the V8 package

shinyjs 0.2.3


  • Updated README

shinyjs 0.2.2


  • added html argument to useShinyjs(), which adds support for using shinyjs in shiny apps that are built with index.html instead of using Shiny UI (more details in the README)
  • refactored internally how shinyjs resources are handled so that the resource path is now prefixed with "shinyjs" or "shinyjs-extend" instead of a random string

shinyjs 0.2.1


  • add a debug parameter to useShinyjs that will cause detailed debugging messages to be printed to the JavaScript console when turned on

shinyjs 0.2.0


  • version bump for CRAN submission

shinyjs 0.1.4


  • refactor JavaScript code to remove code duplication and add better internal documentation
  • bug fix: disabled now works with all input types
  • bug fix: enable/disable did not work on selectInput, sliderInput, and actionButton
  • bug fix: resetting a slider input with a range did not reset the end point, only the start point

shinyjs 0.1.3


  • onclick and onevent now work with dynamically generated elements. Not a trivial fix, but enough people requested it that it was important

shinyjs 0.1.2


Lots of big changes

  • added delay function, which allows you to run code after a specified amount of time has elapsed
  • BREAKING CHANGE - removed delay parameter from hide/show/toggle because the same behaviour can now be achieved using the delay function (if you previously used show(id = "text", delay = 2), you can now use delay(2000, show("text")))
  • added onevent function, which is similar to onclick but can be used for many other different events
  • reset now works with dynamically generated elements (inputs that are created with renderUI)
  • make disabled work for dynamically generated elements
  • removed defunc resettable function

shinyjs 0.1.1


  • better debugging: when a shinyjs JavaScript function is called with a mix of both named and unnamed arguments (which is not allowed), tell the user what function exactly was called. This is done because sometimes a different package doesn't properly namespace its function calls and end up accidentally calling shinyjs functions, which results in weird bugs.
  • add comments to the onclick documentation, to make it clear that it can't work with dynamic UIs
  • improved documentation

shinyjs 0.1.0


  • add support for shinyjs.init function when using extendShinyjs that runs when the page loads. This provides the user a way to register event handlers or do some initializations that automatically run on page load rather than calling it manually in the server
  • add disabled function that initializes a Shiny input in a disabled state
  • add a rmd parameter to useShinyjs that lets you use shinyjs inside interactive R markdown documents (default is FALSE to favour regular Shiny apps)
  • the bulk of the shinyjs JavaScript code is no longer embeded in the HTML as text and is instead linked to as a file. This makes the Shiny app's HTML much cleaner and smaller
  • use htmltools dependency system for handling javascript/css dependencies



  • disable/enable now work for downloadButton elements



  • You no longer need to define the server function with the session parameter! A shiny server function defined as server = function(input, output) {...} can work with shinyjs



  • Fix bug where periods in element names weren't working for some shinyjs functions



  • added an option to allow only a predefined list of colours to select from in colourInput (feature request from Hadley and other Twitter users)



  • add selector param to the disable/enable/toggleState functions and the addClass/removeClass/toggleClass functions so that multiple elements can be targeted in batch
  • added transparentText param to colourInput



  • added a demo app using colourInput that's available via runExample and on my shiny server
  • add a transparency option to colourInput
  • complete refactor of colourInput using a better library that I modified to work well with shiny inputs
  • including multiple useShinyjs() or extendShinyjs() will not result in duplicated HTML anymore. This can be useful if the UI is including a few external UI pieces and they independently make a call to useShinyjs().



  • added colourInput that can be used as an input element to select colours, and its corresponding updateColourInput. This doesn't really fit the shinyjs model of running JS functions, this feels like something very different from the rest of the functions in this package, it might move somewhere else in the future.



  • hidden can now accept multiple tags or a tagList or a list of tags (previously only a single tags was allowed)

  • allow hide/show/toggle to be run on any JQuery selector, not only on a single ID



  • added delay argument to hide/show/toggle so that you can now hide or show an element after a short delay instead of immediately. Useful for showing a message for a few seconds and then fading it away.



  • added text argument to extendShinyjs so that JavaScript code can be provided as a string instead of in a separate file. Useful if your JS code is very short and simple and you don't want to create a new file



  • add extendShinyjs function - allow users to add their own JavaScript functions that can be called as if they are regular R code

  • disable and enable now work for ALL shiny input types

  • show and hide now work for any HTML tag including all shiny input types

  • better onclick behaviour - when set on a shiny input, trigger the event when any part of the input is clicked

  • improve implementation of reset and simplify function call to it



  • add reset function that allows input elements to be reset to their original values

  • add function runjs to run arbitrary javascript code (not recommended to use in published shiny apps)

  • relax R version requirement to 3.1.0

  • look for session object in all parent frames, so that shinyjs functions can work from helper functions and not only from within the main server function

  • refacor internal code

  • update example apps and vignette to include reset function and condition param in toggle functions



  • add a condition argument to toggle/toggleState/toggleClass that allows you to pass a boolean condition to determine if to show/hide (enable/disable, etc) based on that condition. Useful to do things like toggleState(id = "submitBtn", condition = nchar(input$text) >= 3)

  • fix hidden so that if there are elements created dynamically using renderUI, shiny will render them when they are made visible

  • better implementation of toggle

  • using enable/disable/toggleState on a selectize input works

  • better implementation of toggleState



CRAN resubmission



  • bugfixes to onclick() (evaluate expressions in the correct environment)

  • rename alert() to info() because when the app was deployed in a Shiny Server (shinyapps.io or my own shiny server), it was printing the alret twice - probably because shiny server somehow intercepts the alert call too

  • rename innerHTML() to text() to make it more understandable for the average user

  • add add param to onclick()

  • add add param to text()

  • add inlineCSS() function to easily add inline CSS to a Shiny app

  • add documentation to all functions

  • add "demo" example app that provides a safe way to experiment with shinyjs by providing a predetermined set of functions to run

  • add "basic" example app that shows how some shinyjs functions can be used together in a real (very simply) Shiny app

  • add vignette and README, get ready for CRAN submission



New function: onclick - allows the user to run an R expression (including shinyjs expressions) when a specific element in the Shiny app is clicked.



The user is no longer required to set the shiny session or to pass it into any function calls. Every shinyjs function will try to dynamically figure out the correct Shiny session to use. The previous code with explicit sessions is still in the codebase but has been commented out so that it'll be easy to switch back to it in the near future in case the new approach doesn't always work.

This has been a pending change for a while but I was hesitant to use it because I still don't fully understand the call stack and I'm not 100% sure this will always be correct. But it does make sense to me and it seems to work so I'll give it a go.

Reference manual

It appears you don't have a PDF plugin for this browser. You can click here to download the reference manual.


2.0.0 by Dean Attali, a year ago


Report a bug at https://github.com/daattali/shinyjs/issues

Browse source code at https://github.com/cran/shinyjs

Authors: Dean Attali [aut, cre]

Documentation:   PDF Manual  

MIT + file LICENSE license

Imports digest, htmltools, jsonlite, shiny

Suggests knitr, rmarkdown, shinyAce, shinydisconnect, testthat

System requirements: pandoc with https support

Imported by AFM, AMPLE, AdhereRViz, BiasCorrector, CRANsearcher, CSUV, CaPO4Sim, CruzPlot, DCEtool, DIZutils, DataEditR, Eagle, EventDetectGUI, GFD, GFDsurv, GMSE, GWSDAT, GenEst, IOHanalyzer, LDAShiny, LFApp, MDMAPR, OpenRepGrid.ic, PRISMA2020, ProjectionBasedClustering, RALSA, RLumShiny, RadialVisGadgets, ReDaMoR, ReviewR, RobStatTM, RtutoR, SPARTAAS, ShinyQuickStarter, SpatialEpiApp, TreeDist, TreeSearch, Umatrix, addinslist, adepro, airGRteaching, animaltracker, apisensr, arena2r, auth0, bdDwC, bdchecks, bdclean, bestSDP, cjoint, cmsaf, cognitoR, colourpicker, corporaexplorer, coveffectsplot, dPCP, dccvalidator, ddpcr, dextergui, discoveR, dosedesignR, dragulaR, dtwclust, elementR, fdapaceShiny, genogeographer, ggExtra, ggquickeda, gimmeTools, gwpcormapper, isobxr, leafdown, lightsout, lmviz, makemyprior, manipulateWidget, meltt, memapp, miniMeta, mlr3shiny, mmaqshiny, mrMLM.GUI, mstrio, npregfast, oceanis, packagefinder, pguIMP, polished, predictoR, regexSelect, regressoR, safetyGraphics, sdcHierarchies, shinyGovstyle, shinyKGode, shinyML, shinyNotes, shinyauthr, shinydlplot, shinyfilter, shinypanel, shinypanels, shinystan, skpr, soundgen, spectrolab, spotGUI, stminsights, subscreen, trackeRapp, visae, visualFields, voronoiTreemap, wallace, wilson, wppExplorer, xROI, yuimaGUI.

Depended on by RSCAT, ShinyImage, monobinShiny, stmgui.

Suggested by AzureAuth, CNVScope, Clustering, DRomics, EGAnet, EML, HaDeX, MODIStsp, OpenSpecy, PROsetta, RDML, SOMbrero, SemNeT, ShinyItemAnalysis, Sofi, Ternary, TestDesign, VOSONDash, bayesbr, bsem, colorspace, compareGroups, eSDM, googleLanguageR, influential, kgschart, landsepi, microsamplingDesign, pkgsearch, sen2r, shinycssloaders, solvebio, strand, tigerstats, tmaptools, wiad.

See at CRAN