Custom basic_table arguments module

Maciej Nasiński

This vignette will guide you through implementation of custom rtables::basic_table arguments for rtables tables based modules. We will enable 2 ways of updating rtables::basic_table by the end users. The rtables::basic_table specification could be updated with the teal.basic_table_args options variable or a ggplot2_args argument in a tm_g_* module. We still take into account default specification set up by the module creator in the server function, which has the lowest priority.

The implementation should consist of 5 steps:

  1. Adding basic_table_args argument to the tm_t_* function and then its server function. The default should be set to the basic_table_args() function for a single plot. and list(default = basic_table_args()) multi-table modules.
  2. Adding a validation (e.g. stopifnot or checkmate) of the basic_table_args argument to the tm_* function. The validation is more complex for multi-table modules, where the ggplot2_args could be a list. The module creator has to provide a list of plots names, which should be validated at this step and added to the param field in roxygen2. For multi-table modules the step if (is_basic_table_args) basic_table_args <- list(default = basic_table_args) is recommended.
  3. Aggregating and reducing all basic_table_args sources with resolve_basic_table_args().
  4. Usage of the parse_basic_table_args() function which will aggregate and reduce all inputs to one expression.
  5. Adding the created expression to the chunk with a table.

The parse_basic_table_args() function picks the first non NULL value for each argument, checking in order:

  1. basic_table_args argument provided by the end user. For multi-table case, per table (basic_table_args_table) and then default (basic_table_args_default) setup.
  2. Global R variable (options), teal.basic_table_args.
  3. basic_table_args_developer which is a developer setup, lowest priority.

Example - Single-Table Module

options("teal.basic_table_args" = teal.widgets::basic_table_args(title = "ENV_TITLE"))
library(shiny)
library(teal.widgets)
library(magrittr)

basic_table_args <- list(
  default = basic_table_args(prov_footer = "USER_FOOTER"),
  table1 = basic_table_args(subtitles = "USER_SUBTITLES_TABLE1"),
  table2 = basic_table_args(subtitles = "USER_SUBTITLES_TABLE2")
)

app <- shinyApp(
  ui = fluidPage(
    shinyjs::useShinyjs(),
    div(verbatimTextOutput("table1"))
  ),
  server = function(input, output, session) {
    dev_table_args <- teal.widgets::basic_table_args(show_colcounts = TRUE)

    table_expr <- substitute(
      expr = {
        tt <- f_table_expr %>%
          rtables::split_cols_by("Species") %>%
          rtables::analyze(vars = "Sepal.Length", afun = function(x) {
            rtables::in_rows(
              "Mean" = rtables::rcell(mean(x), format = "xx.xx"),
              "Range" = rtables::rcell(range(x), format = "xx.xx - xx.xx")
            )
          })
        table2 <- rtables::build_table(tt, iris)
        table2
      },
      env = list(f_table_expr = parse_basic_table_args(
        teal.widgets::resolve_basic_table_args(
          user_table = basic_table_args$table2,
          user_default = basic_table_args$default,
          module_table = dev_table_args
        )
      ))
    )
    output$table1 <- renderPrint(eval(table_expr))
  }
)
shinyApp(app$ui, app$server)