Search code examples
htmlrshinycodemirror

Need to display dynamic text generated from server onto UI within a TextArea(with syntax highlighting)


I am trying to push a randomly generated string onto a textarea on UI. New to HTML/Shiny/JS but I know a few basics.

My end goal is to use CodeMirror (Whole download) or ShinyAce editor classes to add syntax highlighting to the textarea but I am unable to output strings from server into the textarea. I wish to push a certain R Code in textStringToDisplay and need syntax highlighting.

Please put the following files in the www folder of the app.R:

  1. codemirror.css
  2. cobalt.css
  3. codemirror.js (I could not find this file on GitHub, please use the download link above, extract and look in the lib folder)
  4. r.js

Please let me know if you need more information or if I should rephrase any parts of this. Thanks in advance.

library(shiny)

if (interactive()) {

  ui <- shinyUI(
    fluidPage(
      tags$head(tags$title("Title"),
                tags$link(rel = "stylesheet", href = "codemirror.css"),
                tags$link(rel = "stylesheet", href = "cobalt.css"),
                tags$script(src = "codemirror.js"),
                tags$script(src = "r.js")
      ),
      tags$textarea(id="textBox", name = "Feedback", textOutput(outputId = "textStringToDisplay")),
      tags$script(
        'var editorR = CodeMirror.fromTextArea(textBox, {
        mode: "r",
        lineNumbers: true,
        smartindent: true
});
        editorR.setOption("theme", "cobalt");
        editorR.setSize("50%","100%");')))

  server <- function(input, output){
    output$textStringToDisplay <- renderText(paste0(sample(letters,15),collapse = ""))
  }

  shinyApp(ui = ui, server = server)
}

Solution

  • Here's my final implementation. Would like to thank @Bertil for his suggestion regarding renderUI. Had to use shinyjs package and the runjs function to get the JS script running. Also it only works when paired with an event (like clicking a button). Do not know how to trigger it when the app loads(will post another question about this sometime later).

    library(shiny) 
    library(shinyjs)
    
    if (interactive()) {
         ui <- shinyUI(
        fluidPage(
          useShinyjs(),
          tags$head(tags$title("Title"),
                    tags$link(rel = "stylesheet", href = "codemirror.css"),
                    tags$link(rel = "stylesheet", href = "cobalt.css"),
                    tags$script(src = "codemirror.js"),
                    tags$script(src = "r.js")
          ),
          actionButton("btn1","Click to see code"),
          uiOutput(outputId = "textStringToDisplay")))
         server <- function(input, output){
        output$textStringToDisplay <- renderUI(
          tags$textarea(id="textBox", name = "Feedback", paste0(sample(letters,15),collapse = "")))
    
        ButtonPressCounter <- 0
    
        observeEvent(input$btn1,
                     {
                       ButtonPressCounter <<- ButtonPressCounter + 1 # Need it to happen only once
                       if(ButtonPressCounter <= 1){
                         shinyjs::runjs(
                           'var editorR = CodeMirror.fromTextArea(textBox, {
                           mode: "r",
                           lineNumbers: true,
                           smartindent: true});
                           editorR.setOption("theme", "cobalt");
                           editorR.setSize("100%","100%");')
                       }
                     })
           }
         shinyApp(ui = ui, server = server) }