I figured I should write this down somewhere as it’s a very useful trick I’ve been using for internal R data packages and might be useful in other R data wrappers that rOpenSci develops and accepts.
Sometimes an R package that wraps a data source includes metadata that we want to make easily accessible and searchable. An example is field codes or abbreviations. For some data sets there can be non-trivial number of codings. We might store these in a separate table that is accessible in the R wrapper package as data or a function that looks like this.
# A tibble: 4 x 3
field code description
<chr> <chr> <chr>
1 field1 A Early State
2 field1 B Medium State
3 field1 C Late Stage
4 field1 D Kaput
This table is useful when provided as package data or via a function like mydata::my_metadata_table()
. One can, for instance, join it to a data extract via the code
field to have more descriptive data. But often this is data that users want to browse or search. I’ve found it helpful in these cases to use the DT package to embed a searchable table in the help documentation of the data.
This is a bit tricky but thanks to the \Sexp{}
macros in R documentation, you can execute arbitrary code in building the HTML of your help file. The trick is creating your HTML file to include all the self-contained javascript code to run the widget. Here’s what I put in the roxygen comments to put a searchable datatable into a helpfile for mypkg::my_metadata_table()
#' \if{html}{ % Only applies to HTML help files
#' \Sexpr[echo=FALSE, results=rd, stage=build]{
#' #This doesn't work for pkgdown pages, so detect if the page is being built in pkgdown and skip the widget
#' in_pkgdown <- any(grepl("as_html.tag_Sexpr", sapply(sys.calls(), function(a) paste(deparse(a), collapse = "\n"))))
#' if(in_pkgdown) {
#' mytext <- c('In RStudio, this help file includes a searchable table of values.')
#' } else {
#' tmp <- tempfile(fileext=".html")
#' #Create a DT htmlwidget and save it to a tempfile
#' htmlwidgets::saveWidget(DT::datatable(mypkg::my_metadata_table(), rownames = FALSE, width=700), tmp)
#' #Read the widget file in, but remove some html tags
#' mytext <- paste('Below is a searchable version of the database codes.',
#' '\\\out{<div style="width:100\%">',
#' paste(stringi::stri_subset_regex(readLines(tmp), "^</?(!DOCTYPE|meta|body|html)",negate=TRUE), collapse="\n"),
#' '</div>}',
#' sep="\n")
#' }
#' mytext
#' }
#' }
#'
#' if{text,latex}{The HTML version of this help file includes a searchable table of the database codes}
(The package needs to import htmlwidgets, DT and stringi)
Here’s the result, in this case from the help of an internal package I created that uses this approach:
Thoughts? I’d be interested if someone has a more robust way to do this that works in pkgdown sites, as well.