Skip to content

Commit 5a27da7

Browse files
authored
Merge branch '1187_decorate_output@main' into tm_missing_data_module@1187_decorate_output@main
2 parents 2c3c297 + 9ef1032 commit 5a27da7

File tree

8 files changed

+240
-59
lines changed

8 files changed

+240
-59
lines changed

R/tm_data_table.R

Lines changed: 62 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@
2929
#'
3030
#' @inherit shared_params return
3131
#'
32+
#' @section Decorating `tm_data_table`:
33+
#'
34+
#' This module generates the following objects, which can be modified in place using decorators:
35+
#' - `table` ([DT::datatable()])
36+
#'
37+
#' For additional details and examples of decorators, refer to the vignette
38+
#' `vignette("decorate-modules-output", package = "teal")` or the [`teal_transform_module()`] documentation.
39+
#'
3240
#' @examplesShinylive
3341
#' library(teal.modules.general)
3442
#' interactive <- function() TRUE
@@ -96,7 +104,8 @@ tm_data_table <- function(label = "Data Table",
96104
),
97105
server_rendering = FALSE,
98106
pre_output = NULL,
99-
post_output = NULL) {
107+
post_output = NULL,
108+
decorators = NULL) {
100109
message("Initializing tm_data_table")
101110

102111
# Start of assertions
@@ -121,6 +130,8 @@ tm_data_table <- function(label = "Data Table",
121130
checkmate::assert_flag(server_rendering)
122131
checkmate::assert_multi_class(pre_output, c("shiny.tag", "shiny.tag.list", "html"), null.ok = TRUE)
123132
checkmate::assert_multi_class(post_output, c("shiny.tag", "shiny.tag.list", "html"), null.ok = TRUE)
133+
134+
checkmate::assert_list(decorators, "teal_transform_module", null.ok = TRUE)
124135
# End of assertions
125136

126137
ans <- module(
@@ -133,7 +144,8 @@ tm_data_table <- function(label = "Data Table",
133144
datasets_selected = datasets_selected,
134145
dt_args = dt_args,
135146
dt_options = dt_options,
136-
server_rendering = server_rendering
147+
server_rendering = server_rendering,
148+
decorators = decorators
137149
),
138150
ui_args = list(
139151
pre_output = pre_output,
@@ -145,9 +157,7 @@ tm_data_table <- function(label = "Data Table",
145157
}
146158

147159
# UI page module
148-
ui_page_data_table <- function(id,
149-
pre_output = NULL,
150-
post_output = NULL) {
160+
ui_page_data_table <- function(id, pre_output = NULL, post_output = NULL) {
151161
ns <- NS(id)
152162

153163
tagList(
@@ -185,7 +195,8 @@ srv_page_data_table <- function(id,
185195
variables_selected,
186196
dt_args,
187197
dt_options,
188-
server_rendering) {
198+
server_rendering,
199+
decorators) {
189200
checkmate::assert_class(data, "reactive")
190201
checkmate::assert_class(isolate(data()), "teal_data")
191202
moduleServer(id, function(input, output, session) {
@@ -238,7 +249,8 @@ srv_page_data_table <- function(id,
238249
ui_data_table(
239250
id = session$ns(x),
240251
choices = choices,
241-
selected = variables_selected
252+
selected = variables_selected,
253+
decorators = decorators
242254
)
243255
)
244256
)
@@ -260,7 +272,8 @@ srv_page_data_table <- function(id,
260272
if_distinct = if_distinct,
261273
dt_args = dt_args,
262274
dt_options = dt_options,
263-
server_rendering = server_rendering
275+
server_rendering = server_rendering,
276+
decorators = decorators
264277
)
265278
}
266279
)
@@ -270,7 +283,8 @@ srv_page_data_table <- function(id,
270283
# UI function for the data_table module
271284
ui_data_table <- function(id,
272285
choices,
273-
selected) {
286+
selected,
287+
decorators) {
274288
ns <- NS(id)
275289

276290
if (!is.null(selected)) {
@@ -282,6 +296,7 @@ ui_data_table <- function(id,
282296
tagList(
283297
teal.widgets::get_dt_rows(ns("data_table"), ns("dt_rows")),
284298
fluidRow(
299+
ui_transform_teal_data(ns("decorate"), transformators = decorators),
285300
teal.widgets::optionalSelectInput(
286301
ns("variables"),
287302
"Select variables:",
@@ -305,7 +320,8 @@ srv_data_table <- function(id,
305320
if_distinct,
306321
dt_args,
307322
dt_options,
308-
server_rendering) {
323+
server_rendering,
324+
decorators) {
309325
moduleServer(id, function(input, output, session) {
310326
iv <- shinyvalidate::InputValidator$new()
311327
iv$add_rule("variables", shinyvalidate::sv_required("Please select valid variable names"))
@@ -314,27 +330,48 @@ srv_data_table <- function(id,
314330
))
315331
iv$enable()
316332

317-
output$data_table <- DT::renderDataTable(server = server_rendering, {
318-
teal::validate_inputs(iv)
319-
333+
data_table_data <- reactive({
320334
df <- data()[[dataname]]
321-
variables <- input$variables
322335

323336
teal::validate_has_data(df, min_nrow = 1L, msg = paste("data", dataname, "is empty"))
324337

325-
dataframe_selected <- if (if_distinct()) {
326-
dplyr::count(df, dplyr::across(dplyr::all_of(variables)))
327-
} else {
328-
df[variables]
329-
}
338+
teal.code::eval_code(
339+
data(),
340+
substitute(
341+
expr = {
342+
variables <- vars
343+
dataframe_selected <- if (if_distinct) {
344+
dplyr::count(dataname, dplyr::across(dplyr::all_of(variables)))
345+
} else {
346+
dataname[variables]
347+
}
348+
dt_args <- args
349+
dt_args$options <- dt_options
350+
if (!is.null(dt_rows)) {
351+
dt_args$options$pageLength <- dt_rows
352+
}
353+
dt_args$data <- dataframe_selected
354+
table <- do.call(DT::datatable, dt_args)
355+
},
356+
env = list(
357+
dataname = as.name(dataname),
358+
if_distinct = if_distinct(),
359+
vars = input$variables,
360+
args = dt_args,
361+
dt_options = dt_options,
362+
dt_rows = input$dt_rows
363+
)
364+
)
365+
)
366+
})
330367

331-
dt_args$options <- dt_options
332-
if (!is.null(input$dt_rows)) {
333-
dt_args$options$pageLength <- input$dt_rows
334-
}
335-
dt_args$data <- dataframe_selected
368+
decorated_data_table_data <-
369+
srv_transform_teal_data("decorate", data = data_table_data, transformators = decorators)
336370

337-
do.call(DT::datatable, dt_args)
371+
output$data_table <- DT::renderDataTable(server = server_rendering, {
372+
req(data_table_data())
373+
teal::validate_inputs(iv)
374+
decorated_data_table_data()[["table"]]
338375
})
339376
})
340377
}

R/tm_g_association.R

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,15 @@
2525
#'
2626
#' @inherit shared_params return
2727
#'
28+
#' @section Decorating `tm_g_association`:
29+
#'
30+
#' This module generates the following objects, which can be modified in place using decorators:
31+
#' - `plot_top` (`ggplot2`)
32+
#' - `plot_bottom` (`ggplot2`)
33+
#'
34+
#' For additional details and examples of decorators, refer to the vignette
35+
#' `vignette("decorate-modules-output", package = "teal")` or the [`teal_transform_module()`] documentation.
36+
#'
2837
#' @examplesShinylive
2938
#' library(teal.modules.general)
3039
#' interactive <- function() TRUE
@@ -130,7 +139,8 @@ tm_g_association <- function(label = "Association",
130139
association_theme = c("gray", "bw", "linedraw", "light", "dark", "minimal", "classic", "void"), # nolint: line_length.
131140
pre_output = NULL,
132141
post_output = NULL,
133-
ggplot2_args = teal.widgets::ggplot2_args()) {
142+
ggplot2_args = teal.widgets::ggplot2_args(),
143+
decorators = NULL) {
134144
message("Initializing tm_g_association")
135145

136146
# Normalize the parameters
@@ -166,6 +176,7 @@ tm_g_association <- function(label = "Association",
166176
plot_choices <- c("Bivariate1", "Bivariate2")
167177
checkmate::assert_list(ggplot2_args, types = "ggplot2_args")
168178
checkmate::assert_subset(names(ggplot2_args), c("default", plot_choices))
179+
checkmate::assert_list(decorators, "teal_transform_module", null.ok = TRUE)
169180
# End of assertions
170181

171182
# Make UI args
@@ -183,7 +194,7 @@ tm_g_association <- function(label = "Association",
183194
ui_args = args,
184195
server_args = c(
185196
data_extract_list,
186-
list(plot_height = plot_height, plot_width = plot_width, ggplot2_args = ggplot2_args)
197+
list(plot_height = plot_height, plot_width = plot_width, ggplot2_args = ggplot2_args, decorators = decorators)
187198
),
188199
datanames = teal.transform::get_extract_datanames(data_extract_list)
189200
)
@@ -236,6 +247,7 @@ ui_tm_g_association <- function(id, ...) {
236247
"Log transformed",
237248
value = FALSE
238249
),
250+
ui_transform_teal_data(ns("decorate"), transformators = args$decorators),
239251
teal.widgets::panel_group(
240252
teal.widgets::panel_item(
241253
title = "Plot settings",
@@ -277,7 +289,8 @@ srv_tm_g_association <- function(id,
277289
vars,
278290
plot_height,
279291
plot_width,
280-
ggplot2_args) {
292+
ggplot2_args,
293+
decorators) {
281294
with_reporter <- !missing(reporter) && inherits(reporter, "Reporter")
282295
with_filter <- !missing(filter_panel_api) && inherits(filter_panel_api, "FilterPanelAPI")
283296
checkmate::assert_class(data, "reactive")
@@ -463,7 +476,6 @@ srv_tm_g_association <- function(id,
463476
)
464477
)
465478
}
466-
467479
teal.code::eval_code(
468480
merged$anl_q_r(),
469481
substitute(
@@ -474,10 +486,8 @@ srv_tm_g_association <- function(id,
474486
teal.code::eval_code(
475487
substitute(
476488
expr = {
477-
plots <- plot_calls
478-
p <- tern::stack_grobs(grobs = lapply(plots, ggplotGrob))
479-
grid::grid.newpage()
480-
grid::grid.draw(p)
489+
plot_top <- plot_calls[[1]]
490+
plot_bottom <- plot_calls[[1]]
481491
},
482492
env = list(
483493
plot_calls = do.call(
@@ -490,9 +500,23 @@ srv_tm_g_association <- function(id,
490500
)
491501
})
492502

503+
decorated_output_q <- srv_transform_teal_data("decorate", data = output_q, transformators = decorators)
504+
decorated_output_grob_q <- reactive({
505+
within(
506+
decorated_output_q(),
507+
{
508+
plot <- tern::stack_grobs(grobs = lapply(list(plot_top, plot_bottom), ggplotGrob))
509+
grid::grid.newpage()
510+
grid::grid.draw(plot)
511+
}
512+
)
513+
})
514+
515+
493516
plot_r <- reactive({
494517
req(iv_r()$is_valid())
495-
output_q()[["p"]]
518+
req(output_q())
519+
decorated_output_grob_q()[["plot"]]
496520
})
497521

498522
pws <- teal.widgets::plot_with_settings_srv(
@@ -508,7 +532,7 @@ srv_tm_g_association <- function(id,
508532

509533
teal.widgets::verbatim_popup_srv(
510534
id = "rcode",
511-
verbatim_content = reactive(teal.code::get_code(output_q())),
535+
verbatim_content = reactive(teal.code::get_code(req(decorated_output_q()))),
512536
title = "Association Plot"
513537
)
514538

@@ -527,7 +551,7 @@ srv_tm_g_association <- function(id,
527551
card$append_text("Comment", "header3")
528552
card$append_text(comment)
529553
}
530-
card$append_src(teal.code::get_code(output_q()))
554+
card$append_src(teal.code::get_code(req(decorated_output_q())))
531555
card
532556
}
533557
teal.reporter::simple_reporter_srv("simple_reporter", reporter = reporter, card_fun = card_fun)

0 commit comments

Comments
 (0)