Introduction
This post covers how you can implement HTML or Text Editor in a Shiny App. We are using open source TinyMCE javascript for text editor. It is one of the most popular text editor used by several famous blogs or websites. It allows several customization tools for styling such as font size and color, bullet and numbered list, table creation, alignment etc.
Use Cases for Online Text Editor
There are many scenarios where you need online text editor. Some of them are as follows -
- In the human resource management tool wherein you ask employees to submit their goals and write accomplishment and areas of improvement. Bullet and Numbered list are key formatting methods which would assist employees to list down their content. Employees can also copy content from MS Word and editor would preserve the formatting
- Suppose you are building a web app for customer feedback. You would allow customers to provide open-ended comments in the app. Rich Text Editor would help your users to describe their issues in clear manner.
- You write blogs and want HTML quickly for your (complete or partial) content. PS - I used it for this blog
Installation
I am glad to release R package named ShinyEditor
for this. You can install it from github. It is not available in CRAN yet.
remotes::install_github("deepanshu88/ShinyEditor")
You also need an API key from Tiny website. You just need signup, it's absolutely free and straightforward to get an API. Once done, you will see API key. You also need to submit your domains where you want to deploy text editor. For example, if you want TinyMCE to implement on listendata.com, type that into the Domain name field and click Add domain. You can add more than one domain.
Demo
I deployed app on shinyapps.io. You can see demo here
HTML Editor in Shiny
Below is the simple example how you can use ShinyEditor
package. Make sure to enter your API key here use_editor("API-Key")
The following program would run even if you don't enter your API key but it throws an error message that your API key is incorrect.
library(shiny) library(ShinyEditor) # UI ui <- fluidPage( # Setup use_editor("API-Key"), titlePanel("HTML Generator"), # Text Input 1 fluidRow( column( width = 6, editor('textcontent'), br(), actionButton( "generatehtml", "Generate HTML Code", icon = icon("code"), class = "btn-primary" )), column( width = 6, tags$pre(textOutput("rawText")) ) ) ) # Server server <- function(input, output, session) { # Generate HTML observeEvent(input$generatehtml, { editorText(session, editorid = 'textcontent', outputid = 'mytext') output$rawText <- renderText({ req(input$mytext) enc2utf8(input$mytext) }) }) } # Run App shinyApp(ui = ui, server = server)
Options to customize Editor
In the editor( )
function you have parameter named options
to customise editor. You can look at tinyMCE website to see the complete list of options permitted.
library(shiny)
library(ShinyEditor)
# UI
ui <- fluidPage(
# Setup
use_editor("API-Key"),
titlePanel("HTML Generator"),
# Text Input 1
fluidRow(
column(
width = 6,
editor('textcontent', text = "Sample Text",
options = "branding: false,
height: 300,
plugins: ['lists', 'table', 'link', 'image', 'code'],
toolbar1: 'bold italic forecolor backcolor | formatselect fontselect fontsizeselect | alignleft aligncenter alignright alignjustify',
toolbar2: 'undo redo removeformat bullist numlist table blockquote code superscript subscript strikethrough link image'"),
br(),
actionButton(
"generatehtml",
"Generate HTML Code",
icon = icon("code"),
class = "btn-primary"
)),
column(
width = 6,
tags$pre(textOutput("rawText"))
)
)
)
# Server
server <- function(input, output, session) {
# Generate HTML
observeEvent(input$generatehtml, {
editorText(session, editorid = 'textcontent', outputid = 'mytext')
output$rawText <- renderText({
req(input$mytext)
enc2utf8(input$mytext)
})
})
}
# Run App
shinyApp(ui = ui, server = server)
Print real-time HTML Conversion
Suppose you want to show real-time HTML of content written by user. In the program below, real-time HTML is shown in the right-hand sided box as soon as user enters some text in the editor.
library(shiny)
library(ShinyEditor)
# UI
ui <- fluidPage(
# Setup
use_editor("API-Key"),
titlePanel("HTML Generator"),
# Text Input 1
fluidRow(
column(
width = 6,
editor('textcontent')
),
column(
width = 6,
tags$pre(textOutput("rawText"))
)
)
)
# Server
server <- function(input, output, session) {
# Generate HTML
values <- reactiveValues(a = NULL)
observe({
editorText(session, editorid = 'textcontent', outputid = 'mytext')
req(input$mytext)
values$a <- enc2utf8(input$mytext)
})
output$rawText <- renderText({
req(values$a)
values$a
})
}
# Run App
shinyApp(ui = ui, server = server)
Update Editor
Package allows you to update editor on client side via UpdateEditor( )
function. See the complete example below.
library(shiny) library(ShinyEditor) # UI ui <- fluidPage( # Setup use_editor("API-Key"), titlePanel("HTML Generator"), # Text Input 1 fluidRow( column( width = 6, editor('textcontent'), br(), actionButton( "generatehtml", "Generate HTML Code", icon = icon("code"), class = "btn-primary" ), actionButton("updatedata", "Update Editor", icon = icon("edit"))), column( width = 6, tags$pre(textOutput("rawText")) ) ) ) # Server server <- function(input, output, session) { # Generate HTML observeEvent(input$generatehtml, { editorText(session, editorid = 'textcontent', outputid = 'mytext') output$rawText <- renderText({ req(input$mytext) enc2utf8(input$mytext) }) }) observeEvent(input$updatedata, { UpdateEditor(session, id = "textcontent", text = "<b>Sample Text</b>") }) } # Run App shinyApp(ui = ui, server = server)
I had my Tiny API Key and I used the command as the same as you guide, like this:
ReplyDeleteuse_editor("my_api_tiny_key")
However, shiny App also display error:
"This domain is not register with Tiny Cloud. Please review your appoved domain"
I registered this API key for local host.
Thanks so much
It's so weird. Try with uploading it on shinyapps.io and register the API key for the same
DeleteThanks a lot for replying my question, I will try it again.
DeleteThanks again,
Is there a way to save long (500-1000-word) inputs into an AWS S3 bucket?
ReplyDeleteThat's outside the scope of this package. Thanks!
DeleteThanks for the prompt response! I see that in your server, you're saving it to value$a. Do you know the length or wordcount limitations saving it to a local object like this? Once it's saved in R I can easily send to AWS or whatever repository externally. I was typing in your demo, but didn't test there so I don't crash your shinyapps.io implementation. Thanks for the hard work on this!
Delete