Introduction
This post explains how to implement Copy text to clipboard functionality in a Shiny App. This is based on clipboard.js javascript which is a lightweight JS sized only 3KB. We have also included tooltip which shows Copied once clicked on the button. This package is useful when you want to allow user to copy content from shiny app.
Installation
I am glad to release R package named shinyCopy2clipboard
for this. You can install it from github. It is not available in CRAN yet.
remotes::install_github("deepanshu88/shinyCopy2clipboard")
Demo
I deployed app on shinyapps.io which has option to copy generated HTML to clipboard. You can see demo here
Basic Example
In the example below we have a text input. We are asking user to enter text in the widget. Entered text will be copied via clicking on the button. If user does not enter text and click on the button it shows "No Text Found".
library(shiny) library(shinyCopy2clipboard) # UI ui <- fluidPage( # Setup use_copy(), # Text Input 1 textInput("text", "Enter Your Text"), # Copy Button 1 CopyButton( "copybtn", label = "Copy to clipboard", icon = icon("copy"), text = "No Text Found" ) ) # Server server <- function(input, output, session) { observe({ req(input$copybtn) CopyButtonUpdate(session, id = "copybtn", label = "Copy to clipboard", icon = icon("copy"), text = input$text ) }) } # Run App shinyApp(ui = ui, server = server)
In the server we have CopyButtonUpdate( )
which can store strings or values from any widget, be it text input, text area, datatable etc. You just need to store it in reactive expression and pass it in text
argument of CopyButtonUpdate( )
. You can also change the icon after user press the button.
Customize Button : Showing SVG
Here we are showing SVG instead of text label. That's how it looks -
library(shiny) library(shinyCopy2clipboard) # UI ui <- fluidPage( # Setup use_copy(), # Text Input 1 textInput("text", "Enter Your Text"), # Copy Button 1 CopyButton( "copybtn", label = HTML('<img src="copy2clipboard-assets/clippy.svg" width="13" alt="Copy to clipboard">'), text = "No Text Found" ) ) # Server server <- function(input, output, session) { observe({ req(input$copybtn) CopyButtonUpdate(session, id = "copybtn", label = HTML('<img src="copy2clipboard-assets/clippy.svg" width="13" alt="Copy to clipboard">'), text = input$text ) }) } # Run App shinyApp(ui = ui, server = server)To show SVG next to textInput you can use
style =
argument in copyButton( ) function and wrap both the widgets in form.
library(shiny) library(shinyCopy2clipboard) # UI ui <- fluidPage( # Setup use_copy(), tags$form(class="form-inline", # Text Input 1 textInput("text", "Enter Your Text"), # Copy Button 1 CopyButton( "copybtn", label = HTML('<img src="copy2clipboard-assets/clippy.svg" width="13" alt="Copy to clipboard">'), text = "No Text Found", style = "margin-left: -7em; margin-top: 1.5em;" ) ) ) # Server server <- function(input, output, session) { observe({ req(input$copybtn) CopyButtonUpdate(session, id = "copybtn", label = HTML('<img src="copy2clipboard-assets/clippy.svg" width="13" alt="Copy to clipboard">'), text = input$text ) }) } # Run App shinyApp(ui = ui, server = server)
Show Copy to Clipboard Button in Modal
You need to set modal = TRUE
to make it work in modal. Following example shows multiple buttons and modal.
library(shiny) library(shinyCopy2clipboard) # The UI ui <- fluidPage( # Load use_copy(), # Text Input 1 textInput("text", "Enter Your Text", "Hello World!"), # Copy Button 1 CopyButton( "copybtn", "Copy to Clipboard", icon = icon("copy"), text = "No Text Found", class = "btn-primary", width = "150px" ), br(), br(), # Text Input 2 textInput("text2", "Enter Your Text"), # Copy Button 2 CopyButton( "copybtn2", "Copy to Clipboard", icon = icon("copy"), text = "No Text Found", class = "btn-primary" ), br(), br(), # Button for Modal actionButton('mdl', 'Show Button in Modal') ) # The server server <- function(input, output, session) { observeEvent(input$mdl, { shiny::showModal( modalDialog( textInput("text3", "Enter your comments"), CopyButton( "copybtn3", "Copy to Clipboard", icon = icon("copy"), text = "No Text Found", class = "btn-primary", modal = TRUE ) ) ) }) observe({ CopyButtonUpdate(session, id = "copybtn", label = "Copy to Clipboard", icon = icon("copy"), text = input$text ) }) observe({ req(input$copybtn2) CopyButtonUpdate(session, id = "copybtn2", label = "Copy to Clipboard", icon = icon("cut"), text = input$text2 ) }) observe({ req(input$copybtn3) CopyButtonUpdate(session, id = "copybtn3", label = "Copy to Clipboard", icon = icon("copy"), text = input$text3, modal = TRUE ) }) } shinyApp(ui = ui, server = server)
Share Share Tweet