From d6a23a676fbec92e43214add750d38da7284a8cc Mon Sep 17 00:00:00 2001 From: Stefan Kuethe Date: Mon, 16 Sep 2024 13:06:55 +0200 Subject: [PATCH 01/12] Add shiny and themes vignettes --- vignettes/articles/rtabulator.Rmd | 4 +++- vignettes/articles/shiny.Rmd | 39 +++++++++++++++++++++++++++++++ vignettes/articles/themes.Rmd | 38 ++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 vignettes/articles/shiny.Rmd create mode 100644 vignettes/articles/themes.Rmd diff --git a/vignettes/articles/rtabulator.Rmd b/vignettes/articles/rtabulator.Rmd index f7f4536..dbd5cc3 100644 --- a/vignettes/articles/rtabulator.Rmd +++ b/vignettes/articles/rtabulator.Rmd @@ -226,4 +226,6 @@ tabulator(NULL, setup) ``` ## Next Steps -Check the [API Reference](../reference/index.html) for details. +* [API Reference](../reference/index.html) +* [Shiny Integration](../articles/shiny.html) +* [Themes](../articles/themes.html) diff --git a/vignettes/articles/shiny.Rmd b/vignettes/articles/shiny.Rmd new file mode 100644 index 0000000..6181ff4 --- /dev/null +++ b/vignettes/articles/shiny.Rmd @@ -0,0 +1,39 @@ +--- +title: "Shiny integration" +--- + +```{r, include = FALSE} +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>" +) +``` + +```{r setup} +library(shiny) +library(rtabulator) +``` + +## Basic application + +Use `tabulatorOutput()` in the UI and `renderTabulator()` in the server part of your Shiny application: + +```{r, eval=FALSE} + +ui <- fluidPage( + titlePanel("Titanic Data Set"), + tabulatorOutput("titanic") +) + +server <- function(input, output) { + output$titanic <- renderTabulator({ + tabulator(titanic()) |> + set_formatter_progress("Fare") |> + set_tooltip("Fare") |> + set_formatter_tick_cross("Survived") |> + set_formatter_star("Pclass", number_of_stars = 3) + }) +} + +shinyApp(ui = ui, server = server) +``` diff --git a/vignettes/articles/themes.Rmd b/vignettes/articles/themes.Rmd new file mode 100644 index 0000000..db86ca0 --- /dev/null +++ b/vignettes/articles/themes.Rmd @@ -0,0 +1,38 @@ +--- +title: "Themes" +--- + +```{r, include = FALSE} +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>" +) +``` + +```{r setup} +library(rtabulator) +``` + +rtabulator comes with the built-in themes of [Tabulator JS](https://tabulator.info/docs/6.2/theme). + +## Standard Themes + +* midnight +* modern +* simple +* site + +## Framework Themes + +* bootstrap3 +* bootstrap4 +* bootstrap5 +* bulma +* materialize +* semanticui + +Themes are selected by specifying the `theme` parameter when calling `tabulator()`: + +```{r} +tabulator(iris, theme = "midnight") +``` From 14f8000db9ab6be686339b2b0578ed4bfd0b3e76 Mon Sep 17 00:00:00 2001 From: Stefan Kuethe Date: Mon, 16 Sep 2024 13:30:05 +0200 Subject: [PATCH 02/12] Add shiny example --- examples/shiny/basic_app/app.R | 19 +++++++++++++++++++ vignettes/articles/shiny.Rmd | 1 - 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 examples/shiny/basic_app/app.R diff --git a/examples/shiny/basic_app/app.R b/examples/shiny/basic_app/app.R new file mode 100644 index 0000000..65b6a8f --- /dev/null +++ b/examples/shiny/basic_app/app.R @@ -0,0 +1,19 @@ +library(shiny) +library(rtabulator) + +ui <- fluidPage( + titlePanel("Titanic Data Set"), + tabulatorOutput("titanic") +) + +server <- function(input, output) { + output$titanic <- renderTabulator({ + tabulator(titanic()) |> + set_formatter_progress("Fare") |> + set_tooltip("Fare") |> + set_formatter_tick_cross("Survived") |> + set_formatter_star("Pclass", number_of_stars = 3) + }) +} + +shinyApp(ui = ui, server = server) diff --git a/vignettes/articles/shiny.Rmd b/vignettes/articles/shiny.Rmd index 6181ff4..b3a9797 100644 --- a/vignettes/articles/shiny.Rmd +++ b/vignettes/articles/shiny.Rmd @@ -19,7 +19,6 @@ library(rtabulator) Use `tabulatorOutput()` in the UI and `renderTabulator()` in the server part of your Shiny application: ```{r, eval=FALSE} - ui <- fluidPage( titlePanel("Titanic Data Set"), tabulatorOutput("titanic") From 0d30f09940cc604b3d9062a31dbff9b2d6e3b770 Mon Sep 17 00:00:00 2001 From: Stefan Kuethe Date: Mon, 16 Sep 2024 15:43:40 +0200 Subject: [PATCH 03/12] Change data type of data returned from JS --- R/utils.R | 6 ++++++ examples/shiny/advanced_app/app.R | 32 +++++++++++++++++++++++++++++++ inst/htmlwidgets/rtabulator.js | 15 +++++++++++++-- 3 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 examples/shiny/advanced_app/app.R diff --git a/R/utils.R b/R/utils.R index ca01baa..aef4ced 100644 --- a/R/utils.R +++ b/R/utils.R @@ -18,3 +18,9 @@ list_to_data_frame <- function(x) { # jsonlite::toJSON(x, auto_unbox = TRUE) |> jsonlite::fromJSON() return(do.call(rbind.data.frame, x)) } + +tabulator_data_as_data_frame <- function(data) { + return(as.data.frame(purrr::map(data, ~ unlist(.x)))) +} + +# as.data.frame(purrr::map(input$data, ~ unlist(.x))) diff --git a/examples/shiny/advanced_app/app.R b/examples/shiny/advanced_app/app.R new file mode 100644 index 0000000..2cd3af5 --- /dev/null +++ b/examples/shiny/advanced_app/app.R @@ -0,0 +1,32 @@ +library(shiny) +library(rtabulator) + +ui <- fluidPage( + titlePanel("Titanic Data Set"), + tabulatorOutput("titanic"), + actionButton("submit", "Submit data to R") +) + +server <- function(input, output) { + output$titanic <- renderTabulator({ + tabulator(titanic(c("PassengerId", "Name", "Pclass", "Sex", "Fare", "Survived"))) |> + set_formatter_progress("Fare") |> + set_tooltip("Fare") |> + set_formatter_tick_cross("Survived") |> + set_formatter_star("Pclass", number_of_stars = 3) + }) + + observeEvent(input$submit, { + print(input$submit) + tabulatorContext("titanic") |> + trigger_get_data() + }) + + observeEvent(input$titanic_get_data, { + print(input$titanic_get_data$data) + print(head(tabulator_data_as_data_frame(input$titanic_get_data$data))) + # print(list_to_data_frame(input$table_data$data)) + }) +} + +shinyApp(ui = ui, server = server) diff --git a/inst/htmlwidgets/rtabulator.js b/inst/htmlwidgets/rtabulator.js index 03e6a3c..80f3d9a 100644 --- a/inst/htmlwidgets/rtabulator.js +++ b/inst/htmlwidgets/rtabulator.js @@ -25,15 +25,26 @@ }); } + // src/utils.js + function convertToDataFrame(data) { + res = {}; + if (data.length === 0) { + return res; + } + keys = Object.keys(data[0]); + keys.forEach((key) => res[key] = data.map((item) => item[key])); + return res; + } + // src/widget.js function run_calls(el, table, calls) { calls.forEach(([method_name, options]) => { if (method_name === "getData") { - const inputName = `${el.id}_data`; + const inputName = `${el.id}_get_data`; console.log("custom call", inputName); Shiny.setInputValue( inputName, - { data: table.getData() }, + { data: convertToDataFrame(table.getData()) }, { priority: "event" } ); return; From 0fa61e756c0da13e953d13ada309aa52fd0b5dd6 Mon Sep 17 00:00:00 2001 From: Stefan Kuethe Date: Tue, 17 Sep 2024 08:36:43 +0200 Subject: [PATCH 04/12] Refactor --- NAMESPACE | 4 ++- R/input_handlers.R | 4 +++ R/tabulator_options.R | 26 ++++++++++---- R/utils.R | 8 +++-- _pkgdown.yml | 3 +- examples/options/group_by_options.R | 2 ++ examples/options/pagination_options.R | 2 ++ man/list_to_data_frame.Rd | 4 +-- ...on_group_by.Rd => set_options_group_by.Rd} | 10 +++--- man/set_options_pagination.Rd | 35 +++++++++++++++++++ man/tabulator_data_as_df.Rd | 14 ++++++++ vignettes/articles/rtabulator.Rmd | 14 ++++++-- 12 files changed, 104 insertions(+), 22 deletions(-) create mode 100644 R/input_handlers.R create mode 100644 examples/options/group_by_options.R create mode 100644 examples/options/pagination_options.R rename man/{set_option_group_by.Rd => set_options_group_by.Rd} (85%) create mode 100644 man/set_options_pagination.Rd create mode 100644 man/tabulator_data_as_df.Rd diff --git a/NAMESPACE b/NAMESPACE index 135544f..75fa6ac 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -25,12 +25,14 @@ export(set_formatter_toggle_switch) export(set_formatter_traffic_light) export(set_header_filter) export(set_multi_column_header) -export(set_option_group_by) +export(set_options_group_by) +export(set_options_pagination) export(set_tooltip) export(spreadsheet_def) export(tabulator) export(tabulatorContext) export(tabulatorOutput) +export(tabulator_data_as_df) export(tabulator_options) export(titanic) export(trigger_download) diff --git a/R/input_handlers.R b/R/input_handlers.R new file mode 100644 index 0000000..1cc94d3 --- /dev/null +++ b/R/input_handlers.R @@ -0,0 +1,4 @@ +# https://book.javascript-for-r.com/shiny-complete.html +input_handler_data <- function(data, ...) { + return(tabulator_data_as_df(data)) +} diff --git a/R/tabulator_options.R b/R/tabulator_options.R index 8fff97c..3ea29e5 100644 --- a/R/tabulator_options.R +++ b/R/tabulator_options.R @@ -96,28 +96,40 @@ default_spreadsheet_options <- list( spreadsheet_column_definition = list(editor = "input") ) -# TODO: Helper function to set pagination -set_option_pagination <- function( +#' Set pagination options +#' @inheritParams set_formatter_html +#' @inheritParams tabulator_options +#' @example examples/options/pagination_options.R +#' @export +set_options_pagination <- function( widget, - pagination = FALSE, + pagination = TRUE, pagination_size = 10, pagination_size_selector = FALSE, pagination_add_row = c("page", "table"), ...) { - return(widget) + # Body + options_update <- list( + pagination = pagination, + paginationSize = pagination_size, + paginationSizeSelector = pagination_size_selector, + paginationAddRow = match.arg(pagination_add_row), + ... + ) + modify_tabulator_options(widget, options_update) } -#' Set group by option +#' Set group by options #' @inheritParams set_formatter_html #' @inheritParams tabulator_options #' @export -set_option_group_by <- function( +set_options_group_by <- function( widget, group_by, group_start_open = TRUE, group_toggle_element = "header", ...) { - # return(widget) + # Body options_update <- list( groupBy = group_by, groupStartOpen = group_start_open, diff --git a/R/utils.R b/R/utils.R index aef4ced..0a5872f 100644 --- a/R/utils.R +++ b/R/utils.R @@ -11,7 +11,7 @@ compact <- function(x) { x[!sapply(x, is.null)] } -#' Parse List to Data Frame +#' Convert a list of names lists to data frame #' @param x (list): A list of named lists. #' @export list_to_data_frame <- function(x) { @@ -19,8 +19,10 @@ list_to_data_frame <- function(x) { return(do.call(rbind.data.frame, x)) } -tabulator_data_as_data_frame <- function(data) { +#' Convert input data to data frame +#' @param data (list): The input data returned in a Shiny app. +#' @export +tabulator_data_as_df <- function(data) { return(as.data.frame(purrr::map(data, ~ unlist(.x)))) } -# as.data.frame(purrr::map(input$data, ~ unlist(.x))) diff --git a/_pkgdown.yml b/_pkgdown.yml index 768d2fd..42308f9 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -9,7 +9,8 @@ reference: contents: - tabulator - tabulator_options - - set_option_group_by + - set_options_group_by + - set_options_pagination - title: Column Settings desc: > diff --git a/examples/options/group_by_options.R b/examples/options/group_by_options.R new file mode 100644 index 0000000..3a8f719 --- /dev/null +++ b/examples/options/group_by_options.R @@ -0,0 +1,2 @@ +tabulator(iris) |> + set_options_group_by("Species", group_start_open = FALSE) diff --git a/examples/options/pagination_options.R b/examples/options/pagination_options.R new file mode 100644 index 0000000..208d742 --- /dev/null +++ b/examples/options/pagination_options.R @@ -0,0 +1,2 @@ +tabulator(iris) |> + set_options_pagination(pagination_size_selector = c(10, 20, 50)) diff --git a/man/list_to_data_frame.Rd b/man/list_to_data_frame.Rd index dc586a4..fb0e2ce 100644 --- a/man/list_to_data_frame.Rd +++ b/man/list_to_data_frame.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/utils.R \name{list_to_data_frame} \alias{list_to_data_frame} -\title{Parse List to Data Frame} +\title{Convert a list of names lists to data frame} \usage{ list_to_data_frame(x) } @@ -10,5 +10,5 @@ list_to_data_frame(x) \item{x}{(list): A list of named lists.} } \description{ -Parse List to Data Frame +Convert a list of names lists to data frame } diff --git a/man/set_option_group_by.Rd b/man/set_options_group_by.Rd similarity index 85% rename from man/set_option_group_by.Rd rename to man/set_options_group_by.Rd index 888a0b4..116d789 100644 --- a/man/set_option_group_by.Rd +++ b/man/set_options_group_by.Rd @@ -1,10 +1,10 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/tabulator_options.R -\name{set_option_group_by} -\alias{set_option_group_by} -\title{Set group by option} +\name{set_options_group_by} +\alias{set_options_group_by} +\title{Set group by options} \usage{ -set_option_group_by( +set_options_group_by( widget, group_by, group_start_open = TRUE, @@ -27,5 +27,5 @@ Set to \code{FALSE} to disable toggling at all.} \item{...}{Further options.} } \description{ -Set group by option +Set group by options } diff --git a/man/set_options_pagination.Rd b/man/set_options_pagination.Rd new file mode 100644 index 0000000..6e59cd9 --- /dev/null +++ b/man/set_options_pagination.Rd @@ -0,0 +1,35 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/tabulator_options.R +\name{set_options_pagination} +\alias{set_options_pagination} +\title{Set pagination options} +\usage{ +set_options_pagination( + widget, + pagination = TRUE, + pagination_size = 10, + pagination_size_selector = FALSE, + pagination_add_row = c("page", "table"), + ... +) +} +\arguments{ +\item{widget}{(\code{\link{tabulator}}) A tabulator widget.} + +\item{pagination}{(bool): Whether to enable pagination.} + +\item{pagination_size}{(integer): Number of rows on each page.} + +\item{pagination_size_selector}{(list): Add pagination size selector.} + +\item{pagination_add_row}{(character): Where to add rows to the table when pagination is enabled.} + +\item{...}{Further options.} +} +\description{ +Set pagination options +} +\examples{ +tabulator(iris) |> + set_options_pagination(pagination_size_selector = c(10, 20, 50)) +} diff --git a/man/tabulator_data_as_df.Rd b/man/tabulator_data_as_df.Rd new file mode 100644 index 0000000..ecc31df --- /dev/null +++ b/man/tabulator_data_as_df.Rd @@ -0,0 +1,14 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utils.R +\name{tabulator_data_as_df} +\alias{tabulator_data_as_df} +\title{Convert input data to data frame} +\usage{ +tabulator_data_as_df(data) +} +\arguments{ +\item{data}{(list): The input data returned in a Shiny app.} +} +\description{ +Convert input data to data frame +} diff --git a/vignettes/articles/rtabulator.Rmd b/vignettes/articles/rtabulator.Rmd index dbd5cc3..32ff7ac 100644 --- a/vignettes/articles/rtabulator.Rmd +++ b/vignettes/articles/rtabulator.Rmd @@ -27,7 +27,7 @@ tabulator(airquality) In this case, the column definitions are automatically created for you. The horizontal alignment for character columns is set to _left_ while numeric columns are aligned _right_. -It is also possible to pass pass a data URL: +It is also possible to pass a data URL: ```{r} data_url <- "https://raw.githubusercontent.com/eodaGmbH/rtabulator/main/data-raw/titanic.csv" @@ -64,6 +64,14 @@ setup <- tabulator_options( tabulator(USArrests, setup) ``` +*** + +**Note** + +If you prefer the pipe style, you can also use the helper function `set_options_pagination()`. + +*** + ## Column Formatters To customize your columns, the easiest way is to use the `set_formatter_*()` functions: @@ -75,7 +83,7 @@ tabulator(airquality) |> set_tooltip("Ozone") ``` -With `for_each_col()` you can apply a formatter to multiple columns: +With `for_each_col()` you can apply a formatter and any other function that updates the column settings to multiple columns: ```{r} numeric_cols <- c("Sepal_Length", "Sepal_Width", "Petal_Length", "Petal_Width") @@ -146,7 +154,7 @@ tabulator(titanic_df, setup) **Note** -You can also use `set_option_group_by()` to set the group by options. +You can also use `set_options_group_by()` to set the group by options. *** From d4ad2ac5f7da3f2295c47396258ad7d4848f5aaf Mon Sep 17 00:00:00 2001 From: Stefan Kuethe Date: Tue, 17 Sep 2024 11:00:10 +0200 Subject: [PATCH 05/12] Remove some exports --- NAMESPACE | 2 -- R/input_handlers.R | 18 ++++++++++++++++-- R/package.R | 3 +++ R/utils.R | 19 +++++++++++-------- R/zzz.R | 6 ++++++ _pkgdown.yml | 1 - examples/shiny/advanced_app/app.R | 4 ++-- examples/shiny/spreadsheet/app.R | 9 ++++++++- inst/htmlwidgets/rtabulator.js | 2 +- man/list_to_data_frame.Rd | 14 -------------- man/tabulator_data_as_df.Rd | 14 -------------- 11 files changed, 47 insertions(+), 45 deletions(-) create mode 100644 R/package.R create mode 100644 R/zzz.R delete mode 100644 man/list_to_data_frame.Rd delete mode 100644 man/tabulator_data_as_df.Rd diff --git a/NAMESPACE b/NAMESPACE index 75fa6ac..38fa734 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -4,7 +4,6 @@ export(add_row) export(create_columns) export(delete_selected_rows) export(for_each_col) -export(list_to_data_frame) export(redo) export(renderTabulator) export(set_calculation) @@ -32,7 +31,6 @@ export(spreadsheet_def) export(tabulator) export(tabulatorContext) export(tabulatorOutput) -export(tabulator_data_as_df) export(tabulator_options) export(titanic) export(trigger_download) diff --git a/R/input_handlers.R b/R/input_handlers.R index 1cc94d3..e9babd3 100644 --- a/R/input_handlers.R +++ b/R/input_handlers.R @@ -1,4 +1,18 @@ # https://book.javascript-for-r.com/shiny-complete.html -input_handler_data <- function(data, ...) { - return(tabulator_data_as_df(data)) +input_handler_data <- function(value, ...) { + if (debug_mode()) { + print("custom input handler data") + } + + data <- value$data + try(data <- tabulator_data_as_df(value$data)) + + return(data) +} + +# TODO: Not used at the moment +input_handler_sheet_data <- function(value, ...) { + data <- value$data + # try(jsonlite::fromJSON(jsonlite::toJSON(value, auto_unbox = TRUE))) + return(data) } diff --git a/R/package.R b/R/package.R new file mode 100644 index 0000000..2b0302a --- /dev/null +++ b/R/package.R @@ -0,0 +1,3 @@ +debug_mode <- function() { + return(getOption("rtabulator.debug", FALSE)) +} diff --git a/R/utils.R b/R/utils.R index 0a5872f..3852c5f 100644 --- a/R/utils.R +++ b/R/utils.R @@ -6,23 +6,26 @@ keys_to_camel_case <- function(x) { stats::setNames(x, to_camel_case(names(x))) } -# Remove NULL values from list +# Drop NULL values from list compact <- function(x) { x[!sapply(x, is.null)] } -#' Convert a list of names lists to data frame -#' @param x (list): A list of named lists. -#' @export +# Convert list of named lists to data frame list_to_data_frame <- function(x) { # jsonlite::toJSON(x, auto_unbox = TRUE) |> jsonlite::fromJSON() return(do.call(rbind.data.frame, x)) } -#' Convert input data to data frame -#' @param data (list): The input data returned in a Shiny app. -#' @export +# Convert data returned from JavaScript #### + +as_NA <- function(...) NA + +as_vec <- function(l) { + unlist(purrr::modify_if(l, is.null, as_NA)) +} + tabulator_data_as_df <- function(data) { - return(as.data.frame(purrr::map(data, ~ unlist(.x)))) + return(as.data.frame(purrr::map(data, ~ as_vec(.x)))) } diff --git a/R/zzz.R b/R/zzz.R new file mode 100644 index 0000000..4047242 --- /dev/null +++ b/R/zzz.R @@ -0,0 +1,6 @@ +.onLoad <- function(libname, pkgname) { + # For devtools::load_all() we need to remove to handler if it is already registered + try(shiny::removeInputHandler("rtabulator.data"), silent = TRUE) + + try(shiny::registerInputHandler("rtabulator.data", input_handler_data)) +} diff --git a/_pkgdown.yml b/_pkgdown.yml index 42308f9..ea3ba67 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -50,7 +50,6 @@ reference: Utitily functions contents: - spreadsheet_def - - list_to_data_frame - create_columns - title: Data Sets diff --git a/examples/shiny/advanced_app/app.R b/examples/shiny/advanced_app/app.R index 2cd3af5..44ae3bc 100644 --- a/examples/shiny/advanced_app/app.R +++ b/examples/shiny/advanced_app/app.R @@ -23,8 +23,8 @@ server <- function(input, output) { }) observeEvent(input$titanic_get_data, { - print(input$titanic_get_data$data) - print(head(tabulator_data_as_data_frame(input$titanic_get_data$data))) + print(input$titanic_get_data) + # print(head(tabulator_data_as_data_frame(input$titanic_get_data$data))) # print(list_to_data_frame(input$table_data$data)) }) } diff --git a/examples/shiny/spreadsheet/app.R b/examples/shiny/spreadsheet/app.R index b0fdcba..cbdd4f2 100644 --- a/examples/shiny/spreadsheet/app.R +++ b/examples/shiny/spreadsheet/app.R @@ -31,12 +31,19 @@ server <- function(input, output) { observe({ print(input$submit) tabulatorContext(TABULATOR_OUTPUT_ID) |> - trigger_get_spreadsheet_data() + trigger_get_spreadsheet_data() # |> trigger_get_data() }) |> bindEvent(input$submit) + #observe({ + # print("get_data") + # # print(head(input$spreadsheet_get_data) |> tibble::as_tibble()) + #}) |> bindEvent(input$spreadsheet_get_data) + observe({ + print("get_spreadsheet_data") print(input$spreadsheet_spreadsheet_data) + browser() }) |> bindEvent(input$spreadsheet_spreadsheet_data) } diff --git a/inst/htmlwidgets/rtabulator.js b/inst/htmlwidgets/rtabulator.js index 80f3d9a..361516f 100644 --- a/inst/htmlwidgets/rtabulator.js +++ b/inst/htmlwidgets/rtabulator.js @@ -40,7 +40,7 @@ function run_calls(el, table, calls) { calls.forEach(([method_name, options]) => { if (method_name === "getData") { - const inputName = `${el.id}_get_data`; + const inputName = `${el.id}_get_data:rtabulator.data`; console.log("custom call", inputName); Shiny.setInputValue( inputName, diff --git a/man/list_to_data_frame.Rd b/man/list_to_data_frame.Rd deleted file mode 100644 index fb0e2ce..0000000 --- a/man/list_to_data_frame.Rd +++ /dev/null @@ -1,14 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/utils.R -\name{list_to_data_frame} -\alias{list_to_data_frame} -\title{Convert a list of names lists to data frame} -\usage{ -list_to_data_frame(x) -} -\arguments{ -\item{x}{(list): A list of named lists.} -} -\description{ -Convert a list of names lists to data frame -} diff --git a/man/tabulator_data_as_df.Rd b/man/tabulator_data_as_df.Rd deleted file mode 100644 index ecc31df..0000000 --- a/man/tabulator_data_as_df.Rd +++ /dev/null @@ -1,14 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/utils.R -\name{tabulator_data_as_df} -\alias{tabulator_data_as_df} -\title{Convert input data to data frame} -\usage{ -tabulator_data_as_df(data) -} -\arguments{ -\item{data}{(list): The input data returned in a Shiny app.} -} -\description{ -Convert input data to data frame -} From f574fdb95e3a3ffb899c5dd423d6fe1f4760b8ca Mon Sep 17 00:00:00 2001 From: Stefan Kuethe Date: Tue, 17 Sep 2024 12:42:24 +0200 Subject: [PATCH 06/12] Register handler for sheet data --- DESCRIPTION | 1 + NAMESPACE | 2 +- R/context_calls.R | 4 ++-- R/input_handlers.R | 2 +- R/zzz.R | 4 +++- examples/shiny/spreadsheet/app.R | 9 ++++----- inst/htmlwidgets/rtabulator.js | 4 ++-- ...get_spreadsheet_data.Rd => trigger_get_sheet_data.Rd} | 6 +++--- 8 files changed, 17 insertions(+), 15 deletions(-) rename man/{trigger_get_spreadsheet_data.Rd => trigger_get_sheet_data.Rd} (69%) diff --git a/DESCRIPTION b/DESCRIPTION index c003d32..460b8dd 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -23,6 +23,7 @@ Imports: glue, htmltools, htmlwidgets, + jsonlite, purrr, readr, shiny diff --git a/NAMESPACE b/NAMESPACE index 38fa734..bd0c0b0 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -35,6 +35,6 @@ export(tabulator_options) export(titanic) export(trigger_download) export(trigger_get_data) -export(trigger_get_spreadsheet_data) +export(trigger_get_sheet_data) export(undo) import(htmlwidgets) diff --git a/R/context_calls.R b/R/context_calls.R index f26d4e2..925fa15 100644 --- a/R/context_calls.R +++ b/R/context_calls.R @@ -51,6 +51,6 @@ redo <- function(ctx) { #' Submit data to R #' @inheritParams trigger_download #' @export -trigger_get_spreadsheet_data <- function(ctx) { - invoke_method(ctx, "getSpreadsheetData") +trigger_get_sheet_data <- function(ctx) { + invoke_method(ctx, "getSheetData") } diff --git a/R/input_handlers.R b/R/input_handlers.R index e9babd3..b58aae8 100644 --- a/R/input_handlers.R +++ b/R/input_handlers.R @@ -13,6 +13,6 @@ input_handler_data <- function(value, ...) { # TODO: Not used at the moment input_handler_sheet_data <- function(value, ...) { data <- value$data - # try(jsonlite::fromJSON(jsonlite::toJSON(value, auto_unbox = TRUE))) + try(data <- jsonlite::fromJSON(jsonlite::toJSON(value$data, auto_unbox = TRUE))) return(data) } diff --git a/R/zzz.R b/R/zzz.R index 4047242..9ec5b8c 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -1,6 +1,8 @@ .onLoad <- function(libname, pkgname) { # For devtools::load_all() we need to remove to handler if it is already registered - try(shiny::removeInputHandler("rtabulator.data"), silent = TRUE) + try(shiny::removeInputHandler("rtabulator.data"), silent = FALSE) + try(shiny::removeInputHandler("rtabulator.sheet_data"), silent = FALSE) try(shiny::registerInputHandler("rtabulator.data", input_handler_data)) + try(shiny::registerInputHandler("rtabulator.sheet_data", input_handler_sheet_data)) } diff --git a/examples/shiny/spreadsheet/app.R b/examples/shiny/spreadsheet/app.R index cbdd4f2..eda3204 100644 --- a/examples/shiny/spreadsheet/app.R +++ b/examples/shiny/spreadsheet/app.R @@ -31,7 +31,7 @@ server <- function(input, output) { observe({ print(input$submit) tabulatorContext(TABULATOR_OUTPUT_ID) |> - trigger_get_spreadsheet_data() # |> trigger_get_data() + trigger_get_sheet_data() # |> trigger_get_data() }) |> bindEvent(input$submit) @@ -41,10 +41,9 @@ server <- function(input, output) { #}) |> bindEvent(input$spreadsheet_get_data) observe({ - print("get_spreadsheet_data") - print(input$spreadsheet_spreadsheet_data) - browser() - }) |> bindEvent(input$spreadsheet_spreadsheet_data) + print("get_sheet_data") + print(input$spreadsheet_get_sheet_data) + }) |> bindEvent(input$spreadsheet_get_sheet_data) } shinyApp(ui = ui, server = server) diff --git a/inst/htmlwidgets/rtabulator.js b/inst/htmlwidgets/rtabulator.js index 361516f..0b4d94d 100644 --- a/inst/htmlwidgets/rtabulator.js +++ b/inst/htmlwidgets/rtabulator.js @@ -58,8 +58,8 @@ }); return; } - if (method_name === "getSpreadsheetData") { - const inputName = `${el.id}_spreadsheet_data`; + if (method_name === "getSheetData") { + const inputName = `${el.id}_get_sheet_data:rtabulator.sheet_data`; console.log("custom call", inputName); Shiny.setInputValue( inputName, diff --git a/man/trigger_get_spreadsheet_data.Rd b/man/trigger_get_sheet_data.Rd similarity index 69% rename from man/trigger_get_spreadsheet_data.Rd rename to man/trigger_get_sheet_data.Rd index 2dca267..7444789 100644 --- a/man/trigger_get_spreadsheet_data.Rd +++ b/man/trigger_get_sheet_data.Rd @@ -1,10 +1,10 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/context_calls.R -\name{trigger_get_spreadsheet_data} -\alias{trigger_get_spreadsheet_data} +\name{trigger_get_sheet_data} +\alias{trigger_get_sheet_data} \title{Submit data to R} \usage{ -trigger_get_spreadsheet_data(ctx) +trigger_get_sheet_data(ctx) } \arguments{ \item{ctx}{(\code{\link{tabulatorContext}}): tabulator context object} From c8680bd77ef7897d3c7d82ab6dcd86cd1a035075 Mon Sep 17 00:00:00 2001 From: Stefan Kuethe Date: Tue, 17 Sep 2024 13:54:25 +0200 Subject: [PATCH 07/12] Refactor --- R/input_handlers.R | 22 ++++++++++++++++++++-- examples/shiny/spreadsheet/app.R | 1 + 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/R/input_handlers.R b/R/input_handlers.R index b58aae8..f424188 100644 --- a/R/input_handlers.R +++ b/R/input_handlers.R @@ -4,15 +4,33 @@ input_handler_data <- function(value, ...) { print("custom input handler data") } + if (getOption("rtabulator.raw_data", FALSE)) { + return(value) + } + data <- value$data try(data <- tabulator_data_as_df(value$data)) - return(data) } # TODO: Not used at the moment input_handler_sheet_data <- function(value, ...) { + if (debug_mode()) { + print("custom input handler data") + } + + if (getOption("rtabulator.raw_data", FALSE)) { + return(value) + } + data <- value$data - try(data <- jsonlite::fromJSON(jsonlite::toJSON(value$data, auto_unbox = TRUE))) + # try(data <- jsonlite::fromJSON(jsonlite::toJSON(value$data, auto_unbox = TRUE))) + try(data <- sheet_data_to_matrix(data), silent = TRUE) return(data) } + +sheet_data_to_matrix <- function(data) { + vec <- unlist(purrr::map(data, ~ as_vec(.x))) + # try({vec <- as.numeric(vec)}) + return(matrix(vec, nrow = length(data), byrow = TRUE)) +} diff --git a/examples/shiny/spreadsheet/app.R b/examples/shiny/spreadsheet/app.R index eda3204..34b9d13 100644 --- a/examples/shiny/spreadsheet/app.R +++ b/examples/shiny/spreadsheet/app.R @@ -43,6 +43,7 @@ server <- function(input, output) { observe({ print("get_sheet_data") print(input$spreadsheet_get_sheet_data) + # browser() }) |> bindEvent(input$spreadsheet_get_sheet_data) } From 79e7785a3b42fb45a0a58ab9160404e4a3ed5867 Mon Sep 17 00:00:00 2001 From: Stefan Kuethe Date: Tue, 17 Sep 2024 14:27:52 +0200 Subject: [PATCH 08/12] Use custom input handler for selected rows --- examples/shiny/titanic/app.R | 31 ++++++++++++++++++++++++++++--- inst/htmlwidgets/rtabulator.js | 26 +++++++++++++------------- 2 files changed, 41 insertions(+), 16 deletions(-) diff --git a/examples/shiny/titanic/app.R b/examples/shiny/titanic/app.R index feccb86..52c3d98 100644 --- a/examples/shiny/titanic/app.R +++ b/examples/shiny/titanic/app.R @@ -1,19 +1,44 @@ library(shiny) -data_url <- "https://raw.githubusercontent.com/datasciencedojo/datasets/master/titanic.csv" +OUTPUT_ID <- "titanic" + +data <- titanic(c("PassengerId", "Pclass", "Survived", "Fare")) +setup <- tabulator_options(selectable_rows = TRUE) ui <- fluidPage( titlePanel("Titanic Data"), - tabulatorOutput("titanic") + tabulatorOutput(OUTPUT_ID), + actionButton("submit", "Submit data to R") ) server <- function(input, output) { output$titanic <- renderTabulator({ - tabulator(data_url, editable = TRUE) |> + tabulator(data, setup, editable = TRUE) |> + set_options_pagination() |> set_formatter_progress("Fare") |> + set_tooltip("Fare") |> set_formatter_tick_cross("Survived") |> set_formatter_star("Pclass", number_of_stars = 3) }) + + observeEvent(input$titanic_row_clicked, { + print(input$titanic_row_clicked) + }) + + observeEvent(input$titanic_rows_selected, { + print(input$titanic_rows_selected) + }) + + observeEvent(input$submit, { + print("Trigger get data") + tabulatorContext(OUTPUT_ID) |> + trigger_get_data() + }) + + observeEvent(input$titanic_get_data, { + print("Got data. Thanx!") + print(head(input$titanic_get_data)) + }) } shinyApp(ui = ui, server = server) diff --git a/inst/htmlwidgets/rtabulator.js b/inst/htmlwidgets/rtabulator.js index 0b4d94d..8f4915d 100644 --- a/inst/htmlwidgets/rtabulator.js +++ b/inst/htmlwidgets/rtabulator.js @@ -1,4 +1,15 @@ (() => { + // src/utils.js + function convertToDataFrame(data) { + res = {}; + if (data.length === 0) { + return res; + } + keys = Object.keys(data[0]); + keys.forEach((key) => res[key] = data.map((item) => item[key])); + return res; + } + // src/events.js function addEventListeners(table, el) { table.on("rowClick", function(e, row) { @@ -7,10 +18,10 @@ Shiny.onInputChange(inputName, row.getData()); }); table.on("rowClick", (e, row) => { - const inputName = `${el.id}_rows_selected`; + const inputName = `${el.id}_rows_selected:rtabulator.data`; const data = table.getSelectedRows().map((row2) => row2.getData()); console.log(inputName, data); - Shiny.onInputChange(inputName, data); + Shiny.onInputChange(inputName, { data: convertToDataFrame(data) }); }); table.on("cellEdited", function(cell) { const inputName = `${el.id}_row_edited`; @@ -25,17 +36,6 @@ }); } - // src/utils.js - function convertToDataFrame(data) { - res = {}; - if (data.length === 0) { - return res; - } - keys = Object.keys(data[0]); - keys.forEach((key) => res[key] = data.map((item) => item[key])); - return res; - } - // src/widget.js function run_calls(el, table, calls) { calls.forEach(([method_name, options]) => { From 0b11aca01fdf516489e4b4cf63e8e36d20cae787 Mon Sep 17 00:00:00 2001 From: Stefan Kuethe Date: Tue, 17 Sep 2024 14:31:59 +0200 Subject: [PATCH 09/12] Style --- R/utils.R | 1 - examples/shiny/spreadsheet/app.R | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/R/utils.R b/R/utils.R index 3852c5f..a257409 100644 --- a/R/utils.R +++ b/R/utils.R @@ -28,4 +28,3 @@ as_vec <- function(l) { tabulator_data_as_df <- function(data) { return(as.data.frame(purrr::map(data, ~ as_vec(.x)))) } - diff --git a/examples/shiny/spreadsheet/app.R b/examples/shiny/spreadsheet/app.R index 34b9d13..5cf1e25 100644 --- a/examples/shiny/spreadsheet/app.R +++ b/examples/shiny/spreadsheet/app.R @@ -35,10 +35,10 @@ server <- function(input, output) { }) |> bindEvent(input$submit) - #observe({ + # observe({ # print("get_data") # # print(head(input$spreadsheet_get_data) |> tibble::as_tibble()) - #}) |> bindEvent(input$spreadsheet_get_data) + # }) |> bindEvent(input$spreadsheet_get_data) observe({ print("get_sheet_data") From 4bf32c36e7b9e5234e43611b504baafe6ae3c6ed Mon Sep 17 00:00:00 2001 From: Stefan Kuethe Date: Tue, 17 Sep 2024 14:41:33 +0200 Subject: [PATCH 10/12] Fix pkgdown site --- _pkgdown.yml | 2 +- vignettes/articles/shiny.Rmd | 66 +++++++++++++++++++++++++++++++++++- 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/_pkgdown.yml b/_pkgdown.yml index ea3ba67..b11a6ff 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -41,7 +41,7 @@ reference: - delete_selected_rows - trigger_download - trigger_get_data - - trigger_get_spreadsheet_data + - trigger_get_sheet_data - undo - redo diff --git a/vignettes/articles/shiny.Rmd b/vignettes/articles/shiny.Rmd index b3a9797..57e98f0 100644 --- a/vignettes/articles/shiny.Rmd +++ b/vignettes/articles/shiny.Rmd @@ -14,7 +14,7 @@ library(shiny) library(rtabulator) ``` -## Basic application +## Basic Usage Use `tabulatorOutput()` in the UI and `renderTabulator()` in the server part of your Shiny application: @@ -36,3 +36,67 @@ server <- function(input, output) { shinyApp(ui = ui, server = server) ``` + +## Interactions + +**Triggers** + +- `trigger_download()` +- `trigger_get_data()` +- `trigger_get_sheet_data()` + +**Events** + +- `{OUTPUT_ID}_row_clicked` +- `{OUTPUT_ID}_rows_selected` +- `{OUTPUT_ID}_data_filtered` +- `{OUTPUT_ID}_get_data` +- `{OUTPUT_ID}_get_sheet_data` +- ... + +```{r, eval=FALSE} +library(shiny) + +OUTPUT_ID <- "titanic" + +data <- titanic(c("PassengerId", "Pclass", "Survived", "Fare")) +setup <- tabulator_options(selectable_rows = TRUE) + +ui <- fluidPage( + titlePanel("Titanic Data"), + tabulatorOutput(OUTPUT_ID), + actionButton("submit", "Submit data to R") +) + +server <- function(input, output) { + output$titanic <- renderTabulator({ + tabulator(data, setup, editable = TRUE) |> + set_options_pagination() |> + set_formatter_progress("Fare") |> + set_tooltip("Fare") |> + set_formatter_tick_cross("Survived") |> + set_formatter_star("Pclass", number_of_stars = 3) + }) + + observeEvent(input$titanic_row_clicked, { + print(input$titanic_row_clicked) + }) + + observeEvent(input$titanic_rows_selected, { + print(input$titanic_rows_selected) + }) + + observeEvent(input$submit, { + print("Trigger get data") + tabulatorContext(OUTPUT_ID) |> + trigger_get_data() + }) + + observeEvent(input$titanic_get_data, { + print("Got data. Thanx!") + print(head(input$titanic_get_data)) + }) +} + +shinyApp(ui = ui, server = server) +``` From d5370e77260787497fad0d6e7ac045c58344d9a9 Mon Sep 17 00:00:00 2001 From: Stefan Kuethe Date: Tue, 17 Sep 2024 17:16:02 +0200 Subject: [PATCH 11/12] Trigger download --- R/context_calls.R | 6 +++++- R/js_dependencies.R | 4 ++-- examples/shiny/titanic/app.R | 22 ++++++++++++++++++++-- inst/htmlwidgets/rtabulator.js | 2 +- man/trigger_download.Rd | 2 +- vignettes/articles/shiny.Rmd | 26 +++++++++++++++++++++++--- 6 files changed, 52 insertions(+), 10 deletions(-) diff --git a/R/context_calls.R b/R/context_calls.R index 925fa15..2ab85b2 100644 --- a/R/context_calls.R +++ b/R/context_calls.R @@ -3,7 +3,11 @@ #' @param type (character): csv, json or xlsx (needs sheetjs: \code{tabulator(..., sheetjs = TRUE)}) #' @param file_name (character): file name #' @export -trigger_download <- function(ctx, type = c("csv", "json", "xlsx"), file_name) { +trigger_download <- function(ctx, type = c("csv", "json", "xlsx"), file_name = NULL) { + if (is.null(file_name)) { + file_name <- glue::glue("data.{type}") + } + invoke_method(ctx, "download", match.arg(type), file_name) } diff --git a/R/js_dependencies.R b/R/js_dependencies.R index be7aa5c..5885b19 100644 --- a/R/js_dependencies.R +++ b/R/js_dependencies.R @@ -6,7 +6,7 @@ sheetjs_dependency <- htmltools::htmlDependency( name = "sheetjs", version = SHEETJS_VERSION, src = list( - href = glue::glue("https://cdn.sheetjs.com/xlsx-{SHEETJS_VERSION}/package/dist/") + href = glue::glue("https://cdn.sheetjs.com/xlsx-{SHEETJS_VERSION}/package/dist") ), script = "xlsx.mini.min.js", all_files = FALSE @@ -17,7 +17,7 @@ luxon_dependency <- htmltools::htmlDependency( name = "luxon", version = LUXON_VERSION, src = list( - href = glue::glue("https://cdn.jsdelivr.net/npm/luxon@{LUXON_VERSION}/build/global/") + href = glue::glue("https://cdn.jsdelivr.net/npm/luxon@{LUXON_VERSION}/build/global") ), script = "luxon.min.js", all_files = FALSE diff --git a/examples/shiny/titanic/app.R b/examples/shiny/titanic/app.R index 52c3d98..491283d 100644 --- a/examples/shiny/titanic/app.R +++ b/examples/shiny/titanic/app.R @@ -3,11 +3,15 @@ library(shiny) OUTPUT_ID <- "titanic" data <- titanic(c("PassengerId", "Pclass", "Survived", "Fare")) -setup <- tabulator_options(selectable_rows = TRUE) +setup <- tabulator_options( + selectable_rows = TRUE, + edit_trigger_event = "focus" +) ui <- fluidPage( titlePanel("Titanic Data"), tabulatorOutput(OUTPUT_ID), + actionButton("download", "Download"), actionButton("submit", "Submit data to R") ) @@ -15,20 +19,34 @@ server <- function(input, output) { output$titanic <- renderTabulator({ tabulator(data, setup, editable = TRUE) |> set_options_pagination() |> - set_formatter_progress("Fare") |> + set_formatter_money( + "Fare", + symbol = "\U00A3", symbol_after = FALSE, precision = 1, hoz_align = "right" + ) |> set_tooltip("Fare") |> set_formatter_tick_cross("Survived") |> set_formatter_star("Pclass", number_of_stars = 3) }) + observeEvent(input$download, { + tabulatorContext(OUTPUT_ID) |> + trigger_download("csv") + }) + observeEvent(input$titanic_row_clicked, { print(input$titanic_row_clicked) }) observeEvent(input$titanic_rows_selected, { + print("rows_selected") print(input$titanic_rows_selected) }) + observeEvent(input$titanic_cell_edited, { + print("cell_edited") + print(input$titanic_cell_edited) + }) + observeEvent(input$submit, { print("Trigger get data") tabulatorContext(OUTPUT_ID) |> diff --git a/inst/htmlwidgets/rtabulator.js b/inst/htmlwidgets/rtabulator.js index 8f4915d..057f478 100644 --- a/inst/htmlwidgets/rtabulator.js +++ b/inst/htmlwidgets/rtabulator.js @@ -24,7 +24,7 @@ Shiny.onInputChange(inputName, { data: convertToDataFrame(data) }); }); table.on("cellEdited", function(cell) { - const inputName = `${el.id}_row_edited`; + const inputName = `${el.id}_cell_edited`; console.log(inputName, cell.getData()); Shiny.onInputChange(inputName, cell.getData()); }); diff --git a/man/trigger_download.Rd b/man/trigger_download.Rd index 9fae69c..5ecaea5 100644 --- a/man/trigger_download.Rd +++ b/man/trigger_download.Rd @@ -4,7 +4,7 @@ \alias{trigger_download} \title{Download table data} \usage{ -trigger_download(ctx, type = c("csv", "json", "xlsx"), file_name) +trigger_download(ctx, type = c("csv", "json", "xlsx"), file_name = NULL) } \arguments{ \item{ctx}{(\code{\link{tabulatorContext}}): tabulator context object} diff --git a/vignettes/articles/shiny.Rmd b/vignettes/articles/shiny.Rmd index 57e98f0..a8ddc51 100644 --- a/vignettes/articles/shiny.Rmd +++ b/vignettes/articles/shiny.Rmd @@ -50,9 +50,11 @@ shinyApp(ui = ui, server = server) - `{OUTPUT_ID}_row_clicked` - `{OUTPUT_ID}_rows_selected` - `{OUTPUT_ID}_data_filtered` +- `{OUTPUT_ID}_cell_edited` - `{OUTPUT_ID}_get_data` - `{OUTPUT_ID}_get_sheet_data` -- ... + +Use `tabulatorContext()` to trigger events. ```{r, eval=FALSE} library(shiny) @@ -60,11 +62,15 @@ library(shiny) OUTPUT_ID <- "titanic" data <- titanic(c("PassengerId", "Pclass", "Survived", "Fare")) -setup <- tabulator_options(selectable_rows = TRUE) +setup <- tabulator_options( + selectable_rows = TRUE, + edit_trigger_event = "focus" +) ui <- fluidPage( titlePanel("Titanic Data"), tabulatorOutput(OUTPUT_ID), + actionButton("download", "Download"), actionButton("submit", "Submit data to R") ) @@ -72,20 +78,34 @@ server <- function(input, output) { output$titanic <- renderTabulator({ tabulator(data, setup, editable = TRUE) |> set_options_pagination() |> - set_formatter_progress("Fare") |> + set_formatter_money( + "Fare", + symbol = "\U00A3", symbol_after = FALSE, precision = 1, hoz_align = "right" + ) |> set_tooltip("Fare") |> set_formatter_tick_cross("Survived") |> set_formatter_star("Pclass", number_of_stars = 3) }) + observeEvent(input$download, { + tabulatorContext(OUTPUT_ID) |> + trigger_download("csv") + }) + observeEvent(input$titanic_row_clicked, { print(input$titanic_row_clicked) }) observeEvent(input$titanic_rows_selected, { + print("rows_selected") print(input$titanic_rows_selected) }) + observeEvent(input$titanic_cell_edited, { + print("cell_edited") + print(input$titanic_cell_edited) + }) + observeEvent(input$submit, { print("Trigger get data") tabulatorContext(OUTPUT_ID) |> From 8607cf6cc33c7f8956a92d08d97ddd1f32c5d326 Mon Sep 17 00:00:00 2001 From: Stefan Kuethe Date: Tue, 17 Sep 2024 17:42:54 +0200 Subject: [PATCH 12/12] Update shiny vignette --- examples/shiny/titanic/app.R | 8 ++++++++ inst/htmlwidgets/rtabulator.js | 4 ++-- vignettes/articles/shiny.Rmd | 21 +++++++++++++++++++-- 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/examples/shiny/titanic/app.R b/examples/shiny/titanic/app.R index 491283d..08ac10c 100644 --- a/examples/shiny/titanic/app.R +++ b/examples/shiny/titanic/app.R @@ -18,6 +18,9 @@ ui <- fluidPage( server <- function(input, output) { output$titanic <- renderTabulator({ tabulator(data, setup, editable = TRUE) |> + set_header_filter("Pclass", "list") |> + set_header_filter("Survived", "list") |> + set_header_filter("Fare", "number", "<=", clearable = TRUE) |> set_options_pagination() |> set_formatter_money( "Fare", @@ -47,6 +50,11 @@ server <- function(input, output) { print(input$titanic_cell_edited) }) + observeEvent(input$titanic_data_filtered, { + print("data_filtered") + print(head(input$titanic_data_filtered)) + }) + observeEvent(input$submit, { print("Trigger get data") tabulatorContext(OUTPUT_ID) |> diff --git a/inst/htmlwidgets/rtabulator.js b/inst/htmlwidgets/rtabulator.js index 057f478..25827a7 100644 --- a/inst/htmlwidgets/rtabulator.js +++ b/inst/htmlwidgets/rtabulator.js @@ -29,10 +29,10 @@ Shiny.onInputChange(inputName, cell.getData()); }); table.on("dataFiltered", function(filters, rows) { - const inputName = `${el.id}_data_filtered`; + const inputName = `${el.id}_data_filtered:rtabulator.data`; const data = rows.map((row) => row.getData()); console.log(inputName, data); - Shiny.onInputChange(inputName, data); + Shiny.onInputChange(inputName, { data: convertToDataFrame(data) }); }); } diff --git a/vignettes/articles/shiny.Rmd b/vignettes/articles/shiny.Rmd index a8ddc51..2a3c857 100644 --- a/vignettes/articles/shiny.Rmd +++ b/vignettes/articles/shiny.Rmd @@ -44,6 +44,11 @@ shinyApp(ui = ui, server = server) - `trigger_download()` - `trigger_get_data()` - `trigger_get_sheet_data()` +- `undo()` +- `redo()` +- `add_row()` +- `delete_row()` +- `delete_selected_rows()` **Events** @@ -54,7 +59,7 @@ shinyApp(ui = ui, server = server) - `{OUTPUT_ID}_get_data` - `{OUTPUT_ID}_get_sheet_data` -Use `tabulatorContext()` to trigger events. +Use `tabulatorContext()` in conjunction with the trigger functions: ```{r, eval=FALSE} library(shiny) @@ -77,10 +82,16 @@ ui <- fluidPage( server <- function(input, output) { output$titanic <- renderTabulator({ tabulator(data, setup, editable = TRUE) |> + set_header_filter("Pclass", "list") |> + set_header_filter("Survived", "list") |> + set_header_filter("Fare", "number", "<=", clearable = TRUE) |> set_options_pagination() |> set_formatter_money( "Fare", - symbol = "\U00A3", symbol_after = FALSE, precision = 1, hoz_align = "right" + symbol = "\U00A3", + symbol_after = FALSE, + precision = 1, + hoz_align = "right" ) |> set_tooltip("Fare") |> set_formatter_tick_cross("Survived") |> @@ -93,6 +104,7 @@ server <- function(input, output) { }) observeEvent(input$titanic_row_clicked, { + print("row_clicked") print(input$titanic_row_clicked) }) @@ -106,6 +118,11 @@ server <- function(input, output) { print(input$titanic_cell_edited) }) + observeEvent(input$titanic_data_filtered, { + print("data_filtered") + print(head(input$titanic_data_filtered)) + }) + observeEvent(input$submit, { print("Trigger get data") tabulatorContext(OUTPUT_ID) |>