85

I want to output multiple lines of text using one renderText() command. However, this does not seem possible. For example, from the shiny tutorial we have truncated code in server.R:

shinyServer(
  function(input, output) {
    output$text1 <- renderText({paste("You have selected", input$var)
    output$text2 <- renderText({paste("You have chosen a range that goes from",
      input$range[1], "to", input$range[2])})
  }
)

and code in ui.R:

shinyUI(pageWithSidebar(

  mainPanel(textOutput("text1"),
            textOutput("text2"))
))

which essentially prints two lines:

You have selected example
You have chosen a range that goes from example range.

Is it possible to combine the two lines output$text1 and output$text2 into one block of code? My efforts so far have failed, e.g.

output$text = renderText({paste("You have selected ", input$var, "\n", "You have chosen a range that goes from", input$range[1], "to", input$range[2])})

Anyone have any ideas?

Alex
  • 15,186
  • 15
  • 73
  • 127

3 Answers3

123

You can use renderUI and htmlOutput instead of renderText and textOutput.

require(shiny)
runApp(list(ui = pageWithSidebar(
  headerPanel("censusVis"),
  sidebarPanel(
    helpText("Create demographic maps with 
      information from the 2010 US Census."),
    selectInput("var", 
                label = "Choose a variable to display",
                choices = c("Percent White", "Percent Black",
                            "Percent Hispanic", "Percent Asian"),
                selected = "Percent White"),
    sliderInput("range", 
                label = "Range of interest:",
                min = 0, max = 100, value = c(0, 100))
  ),
  mainPanel(textOutput("text1"),
            textOutput("text2"),
            htmlOutput("text")
  )
),
server = function(input, output) {
  output$text1 <- renderText({paste("You have selected", input$var)})
  output$text2 <- renderText({paste("You have chosen a range that goes from",
                                    input$range[1], "to", input$range[2])})
  output$text <- renderUI({
    str1 <- paste("You have selected", input$var)
    str2 <- paste("You have chosen a range that goes from",
                  input$range[1], "to", input$range[2])
    HTML(paste(str1, str2, sep = '<br/>'))

  })
}
)
)

Note you need to use <br/> as a line break. Also the text you wish to display needs to be HTML escaped so use the HTML function.

jdharrison
  • 30,085
  • 4
  • 77
  • 89
  • 2
    Thanks. I suppose there is no way to do this without html code? – Alex Apr 27 '14 at 23:18
  • 3
    That `HTML()` wrap is clutch. At first glance I was worried this was a hack and the only available option... But actually most of the code in this answer is from the question's example. It is really simple to switch to `HTML()` inside `renderUI({})`, and then `htmlOutput()` on the `ui.R` side. Nice answer! – Paul 'Joey' McMurdie May 03 '14 at 00:14
  • 4
    @Alex I guess you can also use verbatimTextOutput() instead of textOutput(), but you may not want the gray shading. – Yihui Xie Jul 16 '14 at 21:09
  • 1
    +1 nice answer. How would you format the text inside `HTML()`? For instance, `HTML("paste(str1, str2, sep = '
    ')<\b>")` does not work
    – Antoine Oct 28 '15 at 13:34
  • I have created this [thread](http://stackoverflow.com/questions/33392784/bold-text-in-html-output-r-shiny) if you're interested in answering – Antoine Oct 28 '15 at 13:49
  • For htmlOutput("text") + output$text <- renderUI({...}) you can just do htmlOutput("text") + textOutput(paste(str1, str2, sep = '
    ')). No need for the renderUI or HTML() wrap
    – Isaac Zhao Jul 02 '20 at 15:34
12

According to Joe Cheng:

Uhhh I don't recommend using renderUI and htmlOutput [in the way that is explained in the other answer]. You are taking text that is fundamentally text, and coercing to HTML without escaping (meaning if the text just happens to include a string that contains special HTML characters, it could be parsed incorrectly).

How about this instead:

textOutput("foo"),
tags$style(type="text/css", "#foo {white-space: pre-wrap;}")

(Replace the foo in #foo with the ID of your textOutput)

Community
  • 1
  • 1
theforestecologist
  • 4,667
  • 5
  • 54
  • 91
-3

If you mean that you don't care for the line break:

output$text = renderText({
  paste("You have selected ", input$var, ". You have chosen a range that goes 
  from", input$range[1], "to", input$range[2], ".")
})
Priscilla
  • 5
  • 1