glin / reactable

Interactive data tables for R
https://glin.github.io/reactable
Other
633 stars 80 forks source link

Is there a way to display HTML for fields that appear in expanded row details? #29

Closed smach closed 4 years ago

smach commented 4 years ago

Thanks for this package! I've started playing with the expandable row details, using your examples as guides. However, I haven't been able to make fields that appear in the expanded view display as HTML the way I can with colDef(html = TRUE) for fields in the main row. When I click the row to see the expanded view, fields in there show HTML code as HTML code. Is there some way to show as HTML for fields that display when expanded?

glin commented 4 years ago

Yup, you can provide a column definition to details, and specify html = TRUE:

reactable(
  iris, 
  details = colDef(html = TRUE, details = function(i) "<b>details</b>")
)

(And also demonstrated here: https://glin.github.io/reactable/articles/examples.html#expandable-row-details)

This might seem kind of weird, but the table-level expandable row details is really just a special column with no content in it.

smach commented 4 years ago

Thank you! I'm trying to add a couple of fields in the expandable row details that don't display in the main table row, using the CRAN package sample as a guide. (The code is a bit more complex than I understand right now, showing the limits of copy and paste and modify!) My goal would be if, say, the pkg$Description field variable included text with HTML tags that I wanted to display at HTML, not adding HTML to a fixed string like "details".

I totally understand if you don't have time to answer a question like this. Regardless, I'd like to thank you again for this great package, I'm having fun with it trying out different things. (I'm trying to build my own recipe Shiny app; the expanded info would be recipe ingredients and instructions).

glin commented 4 years ago

Ahh, so you have raw HTML in an HTML tag object, that you want to render as HTML? For example, htmltools::div('<a href="">my link</a>') should be a div with an actual link?

If so, this isn't explicitly supported in reactable. In Shiny, you can use HTML() to mark raw HTML as HTML, but that isn't supported in reactable. It is somewhere on the to-do list though..

Instead, you can make use of a React feature for rendering raw HTML:

html <- function(x, inline = FALSE) {
  container <- if (inline) htmltools::span else htmltools::div
  container(dangerouslySetInnerHTML = list("__html" = x))
}

reactable(
  iris,
  columns = list(
    Sepal.Length = colDef(details = function(i) {
      tagList(
        "<a href='#'>my link</a>",                       # renders an escaped HTML string
        html("<a href='#'>my link</a>", inline = TRUE),  # renders a link wrapped in a span
        html("<a href='#'>my link</a>")                  # renders a link wrapped in a div
      )
    })
  )
)

screenshot of table

This should be safe to rely on, but it does have the limitation of requiring a wrapper tag like <div> or <span>, unlike HTML() in Shiny.

Let me know if you were thinking of something different.

smach commented 4 years ago

I feel better now that I couldn't figure it out myself! That's almost what I want, except if instead of hard-coded "my link", the detail would be an existing column that doesn't show up in the main table but only the expanded detail. For example, change Species to iris$Species <- paste0("<p>&lt;em>", iris$Species, "</em></p>") and then create a reactable with every column showing in the main table except Species, and have Species show in the expanded row displaying the HTML as HTML.

glin commented 4 years ago

You can use the row index argument of the details function to get the right value in the Species column, and then hide the Species column with colDef(show = FALSE) (or alternatively, exclude the column from the data):

html <- function(x, inline = FALSE) {
  container <- if (inline) htmltools::span else htmltools::div
  container(dangerouslySetInnerHTML = list("__html" = x))
}

iris$Species <- paste0("<p><em>", iris$Species, "</em></p>")

reactable(
  iris,
  details = function(index) {
    htmltools::tagList(
      html(iris$Species[index])
    )
  },
  columns = list(
    Species = colDef(show = FALSE)
  )
)
smach commented 4 years ago

That's it exactly. Thank you so much!!