Skip to content

Commit fb28571

Browse files
m7praverissimo
andauthored
introduce decorators for tm_data_table (#799)
Part of https://github.com/insightsengineering/teal/issues/1370 <details><summary> Working Example </summary> ```r devtools::load_all("../teal") devtools::load_all(".") # general data example data <- teal_data() data <- within(data, { require(nestcolor) iris <- iris }) custom_table_decorator_interactive <- teal_transform_module( ui = function(id) { ns <- NS(id) div( selectInput( ns("style"), "Table Style", choices = c("Default", "Striped", "Hover"), selected = "Default" ) ) }, server = function(id, data) { moduleServer(id, function(input, output, session) { reactive({ req(data(), input$style) within(data(), { if (style == "Striped") { table <- DT::formatStyle( table, columns = attr(table$x, "colnames")[-1], target = 'row', backgroundColor = '#f9f9f9' ) } else if (style == "Hover") { table <- DT::formatStyle( table, columns = attr(table$x, "colnames")[-1], target = 'row', backgroundColor = '#f0f0f0' ) } }, style = input$style ) }) }) } ) app <- init( data = data, modules = modules( tm_data_table( variables_selected = list( iris = c("Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width", "Species") ), dt_args = list(caption = "IRIS Table Caption"), decorators = list(custom_table_decorator_interactive) ) ) ) if (interactive()) { shinyApp(app$ui, app$server) } ``` </details> --------- Signed-off-by: Marcin <[email protected]> Co-authored-by: André Veríssimo <[email protected]>
1 parent b6ca759 commit fb28571

File tree

2 files changed

+79
-26
lines changed

2 files changed

+79
-26
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
}

man/tm_data_table.Rd

Lines changed: 17 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)