diff --git a/DESCRIPTION b/DESCRIPTION index 34a5106..c003d32 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,15 +1,16 @@ Package: rtabulator Type: Package Title: R Bindings for Tabulator JS -Version: 0.1.1 -Date: 2024-09-13 +Version: 0.1.1.9000 +Date: 2024-09-15 Authors@R: c( person("Stefan", "Kuethe", email = "crazycapivara@gmail.com", role = c("aut", "cre")), person("Nico", "Friess", email = "nico.friess@eoda.de", role = c("aut")) ) Maintainer: Stefan Kuethe Description: Provides R bindings for 'Tabulator JS' . - Makes it a breeze to create beautiful interactive tables. + Makes it a breeze to create highly customisable interactive tables in markdown documents + and Shiny applications. URL: https://github.com/eodaGmbH/rtabulator https://eodagmbh.github.io/rtabulator/ @@ -20,6 +21,7 @@ LazyData: true RoxygenNote: 7.3.2 Imports: glue, + htmltools, htmlwidgets, purrr, readr, diff --git a/NAMESPACE b/NAMESPACE index a3b3f31..135544f 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -3,10 +3,13 @@ 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_column_editor) +export(set_calculation) +export(set_column_defaults) +export(set_editor) export(set_formatter_color) export(set_formatter_datetime) export(set_formatter_html) @@ -22,11 +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_tooltip) export(spreadsheet_def) export(tabulator) export(tabulatorContext) export(tabulatorOutput) export(tabulator_options) +export(titanic) export(trigger_download) export(trigger_get_data) export(trigger_get_spreadsheet_data) diff --git a/R/columns.R b/R/columns.R index 8dfa8dd..cb211d0 100644 --- a/R/columns.R +++ b/R/columns.R @@ -3,6 +3,7 @@ #' @param editor (bool): Whether to make columns editable. #' @param filter (bool): Whether to add a header filter to the columns. #' @export +# TODO: We do not need to export this func anymore create_columns <- function(data, editor = FALSE, filter = FALSE) { data <- fix_colnames(data) dtype_is_numeric <- sapply(data, is.numeric) @@ -40,6 +41,7 @@ set_auto_id <- function(data) { } # TODO: Add possibility to add editor to specific columns only +# TODO: Check if func is obsolete add_editor_to_columns <- function(columns, data) { dtype_is_numeric <- sapply(data, is.numeric) for (index in 1:length(columns)) { @@ -49,14 +51,35 @@ add_editor_to_columns <- function(columns, data) { return(columns) } +# TODO: Check if func is obsolete add_filter_to_columns <- function(columns) { for (index in 1:length(columns)) { - columns[[index]]$headerFilter <- TRUE # detects column type automatically + columns[[index]]$headerFilter <- TRUE # detects column type automatically if editor type is set } return(columns) } +#' Apply a column setter function to multiple columns +#' @inheritParams set_formatter_html +#' @param columns (character vector): The columns the column setter function (\code{.f}) is applied to. +#' If set to \code{NULL} it is applied to all columns. +#' @param .f (function): The column setter function that updates the column settings. +#' @param ... Arguments that are passed to \code{.f}. +#' @example examples/for_each_col.R +#' @export +for_each_col <- function(widget, columns = NULL, .f, ...) { + if (is.null(columns)) columns <- colnames(widget$x$data) + + args <- list(...) + + for (column in columns) { + widget <- do.call(.f, c(list(widget = widget, column = column), args)) + } + + return(widget) +} + # Formatters #### #' HTML Formatter @@ -193,9 +216,14 @@ set_formatter_link <- function( #' Star Rating Formatter #' @inheritParams set_formatter_html #' @param number_of_stars The maximum number of stars to be displayed. +#' If set to \code{NA}, the maximum value of the column is used. #' @example examples/formatters/formatter_star.R #' @export -set_formatter_star <- function(widget, column, number_of_stars, hoz_align = "center") { +set_formatter_star <- function(widget, column, number_of_stars = NA, hoz_align = "center") { + if (is.na(number_of_stars)) { + number_of_stars <- max(widget$x$data[column]) + } + col_update <- list( formatter = "star", formatterParams = list(stars = number_of_stars), @@ -204,7 +232,6 @@ set_formatter_star <- function(widget, column, number_of_stars, hoz_align = "cen modify_col_def(widget, column, col_update) } - #' Progress Formatter #' @inheritParams set_formatter_html #' @param min (numeric): The minimum value for progress bar. @@ -366,12 +393,12 @@ set_formatter_traffic_light <- function( # Other -#' Make columns editable -#' @inheritParams set_formatter_html -#' @param columns (character vector): Columns the editor is applied to. -#' @param type (character): Either \code{input} or \code{number}. -#' @example examples/formatters/column_editor.R -#' @export +# TODO: Deprecated +# #' Make columns editable +# #' @inheritParams set_formatter_html +# #' @param columns (character vector): Columns the editor is applied to. +# #' @param type (character): Either \code{input} or \code{number}. +# #' @example examples/formatters/column_editor.R set_column_editor <- function(widget, columns, type = c("input", "number")) { col_update <- list(editor = match.arg(type)) for (column in columns) { @@ -381,25 +408,136 @@ set_column_editor <- function(widget, columns, type = c("input", "number")) { return(widget) } -#' Add header filter -#' @inheritParams set_column_editor -#' @param columns (character vector): Columns the editor is applied to. -#' If set to \code{NULL}, the editor is applied to all columns. -#' @example examples/misc/header_filter.R +#' Set editor +#' @inheritParams set_formatter_html +#' @param editor (character): The editor type. +#' @param validator (character vector): One or more validators to validate user input. +#' @param ... Optional editor parameters depending on the selected editor. +#' @seealso +#' \url{https://tabulator.info/docs/6.2/edit} for available editors +#' \url{https://tabulator.info/docs/6.2/validate} for available validators. +#' @example examples/editors.R #' @export -set_header_filter <- function(widget, columns = NULL) { - if (is.null(columns)) { - columns <- colnames(widget$x$data) +set_editor <- function( + widget, + column, + editor = c( + "input", "textarea", "number", "range", + "tickCross", "star", "progress", "date", "time", "datetime", "list" + ), + validator = NULL, + ...) { + # Body + col_update <- list(editor = match.arg(editor), validator = validator) + editor_params <- list(...) + if (length(editor_params) > 0) { + col_update$editorParams <- keys_to_camel_case(compact(editor_params)) } - col_update <- list(headerFilter = TRUE) - for (column in columns) { - widget <- modify_col_def(widget, column, col_update) + modify_col_def(widget, column, col_update) +} + +#' Add header filter to column +#' @inheritParams set_formatter_html +#' @param type (character): The type of the filter. +#' @param values_lookup (bool): Whether to use unique column values for the list filter. +#' @param func (character): The filter function. +#' @param clearable (bool): Whether to display a cross to clear the filter. +#' @param placeholder (character): Text that is displayed when no filter is set. +#' @example examples/misc/header_filter.R +#' @export +set_header_filter <- function( + widget, + column, + type = c("input", "number", "list", "tickCross"), + func = c("like", "=", ">", ">=", "<", "<="), + values_lookup = TRUE, + clearable = TRUE, + placeholder = NULL) { + # Body + if (is.null(type)) { + type <- ifelse(is.numeric(widget$x$data[, column]), "number", "input") + } else { + type <- match.arg(type) } + header_filter_params <- compact(list( + clearable = clearable, + valuesLookup = values_lookup + )) + col_update <- list( + headerFilter = type, + headerFilterPlaceholder = placeholder, + headerFilterFunc = func, + headerFilterParams = header_filter_params + ) + modify_col_def(widget, column, col_update) +} + +#' Add tooltip to column +#' @inheritParams set_formatter_html +#' @example examples/misc/tooltip.R +#' @export +set_tooltip <- function(widget, column) { + modify_col_def(widget, column, list(tooltip = TRUE)) +} + + +#' Set column defaults +#' @inheritParams set_formatter_html +#' @param editor (character, bool): One of \code{"input"} or \code{"number"}. +#' If set to \code{FALSE} cells are not editable. +#' @param header_filter (character, bool): One of \code{"input"} or \code{"number"}. +#' Set to \code{FALSE} to disable header filters. +#' @param header_sort (bool): Whether to enable header sorting. +#' @param tooltip (bool): Whether to show tooltips displaying the cell value. +#' @param width (integer): Fixed width of columns. +#' @param ... Additional settings. +#' @seealso \url{https://tabulator.info/docs/6.2/columns#defaults} +#' @example examples/column_defaults.R +#' @export +set_column_defaults <- function( + widget, + editor = FALSE, + header_filter = FALSE, + header_sort = TRUE, + tooltip = TRUE, + width = NULL, + ...) { + widget$x$options$columnDefaults <- compact(list( + editor = editor, + headerFilter = header_filter, + headerSort = header_sort, + tooltip = tooltip, + width = width, + ... + )) return(widget) } +#' Add a calculation to a column +#' @inheritParams set_formatter_html +#' @param column (character): The column the \code{func} is applied to. +#' @param func (character): The calculation function to be applied +#' to the values of the \code{column}. +#' @param precision (integer) The number of decimals to display. +#' Set to \code{FALSE} to display all decimals. +#' @param pos (character): Position at which calculated values are displayed. +#' @example examples/data_url.R +#' @export +set_calculation <- function( + widget, + column, + func = c("avg", "max", "min", "sum", "count", "unique"), + precision = 2, + pos = c("top", "bottom")) { + # Body + pos <- match.arg(pos) + col_update <- list(match.arg(func), list(precision = precision)) + names(col_update) <- c(paste0(pos, "Calc"), paste0(pos, "CalcParams")) + modify_col_def(widget, column, col_update) +} + # Generics modify_col_def <- function(widget, column, col_update) { diff --git a/R/data.R b/R/data.R new file mode 100644 index 0000000..c6df733 --- /dev/null +++ b/R/data.R @@ -0,0 +1,10 @@ +# Data #### + +#' Titanic data set +#' @param col_select (character vector): Columns to select. +#' @export +titanic <- function(col_select = NULL) { + titanic_data_url <- "https://raw.githubusercontent.com/eodaGmbH/rtabulator/main/data-raw/titanic.csv" + + readr::read_csv(titanic_data_url, col_select = !!col_select, show_col_types = FALSE) +} diff --git a/R/experimental.R b/R/experimental.R index f59f6bb..7772220 100644 --- a/R/experimental.R +++ b/R/experimental.R @@ -31,3 +31,18 @@ find_column <- function(widget, column) { return(column_def) } + +# Themes #### + +get_theme_dependeny <- function( + theme = c("midnight", "modern", "simple", "site", "bootstrap3", "bootstrap4", "bootstrap5", "bulma", "materialize", "semanticui")) { + # Body + theme <- match.arg(theme) + htmltools::htmlDependency( + name = "tabulator-theme", + version = "6.2.5", + src = system.file("htmlwidgets/libs/tabulator", package = "rtabulator"), + stylesheet = glue::glue("tabulator_{theme}.min.css"), + all_files = FALSE + ) +} diff --git a/R/tabulator.R b/R/tabulator.R index 9ef2613..8308aba 100644 --- a/R/tabulator.R +++ b/R/tabulator.R @@ -8,6 +8,8 @@ #' @param sheetjs (bool): Whether to add sheetjs (\url{https://sheetjs.com/}) dependency, #' which is needed for xlsx downloads. #' @param theme (character): Theme to apply to the table. +#' @param col_select (character vector) Columns to select. +#' Passed to \code{\link[readr]{read_csv}} if \code{data} is a file name. #' @param width Width of the widget. #' @param height Height of the widget. #' @param element_id The unique ID of the widget. @@ -21,6 +23,7 @@ tabulator <- function( editable = FALSE, sheetjs = FALSE, theme = c("default", "midnight", "modern", "simple", "site", "bootstrap3", "bootstrap4", "bootstrap5", "bulma", "materialize", "semanticui"), + col_select = NULL, width = NULL, height = NULL, element_id = NULL, @@ -28,7 +31,7 @@ tabulator <- function( if (is.null(options)) options <- list() if (is.character(data)) { - data <- readr::read_csv(data, show_col_types = FALSE) + data <- readr::read_csv(data, show_col_types = FALSE, col_select = !!col_select) } # TODO: Use Pipe, but then we need to set required R Version to > 4.1 @@ -47,7 +50,8 @@ tabulator <- function( } theme <- match.arg(theme) - stylesheet_text <- ifelse(theme == "default", NA, read_tabulator_theme(theme)) + # stylesheet_text <- ifelse(theme == "default", NA, read_tabulator_theme(theme)) + stylesheet_text <- NA x <- list( data = data, @@ -57,6 +61,10 @@ tabulator <- function( # TODO: Make it optional when datetime formatter is called dependencies <- list(luxon_dependency) + # dependencies <- list() + if (theme != "default") { + dependencies <- c(dependencies, list(get_theme_dependeny(theme))) + } if (sheetjs) { dependencies <- c(dependencies, list(sheetjs_dependency)) diff --git a/R/tabulator_options.R b/R/tabulator_options.R index 0bb2be7..8fff97c 100644 --- a/R/tabulator_options.R +++ b/R/tabulator_options.R @@ -14,7 +14,12 @@ #' @param resizable_rows (bool): Allow user to resize rows. #' @param frozen_rows (numeric): Number of frozen rows. #' @param index (character): Field to be used as the unique index for each row. -#' @param group_by (character): Field to group rows by. +#' @param group_by (character vector): Field to group rows by. Pass multiple values +#' for multi level grouping. +#' @param group_start_open (bool vector): Open state of groups when grouping is enabled. +#' The length of the vector depends on the number of levels set with \code{group_by}. +#' @param group_toggle_element (character, bool): One of \code{arrow} or \code{header}. +#' Set to \code{FALSE} to disable toggling at all. #' @param edit_trigger_event (character): Event that triggers a cell edit. #' @param selectable_rows (character, bool, integer) Set to \code{FALSE} to disble row selection. #' If set to \code{TRUE} you can select as many rows as you want. @@ -54,6 +59,8 @@ tabulator_options <- function( index = "id", # Row Grouping group_by = NULL, + group_start_open = TRUE, + group_toggle_element = NULL, # Editing edit_trigger_event = c("dblclick", "click", "focus"), # Selection @@ -88,3 +95,42 @@ default_spreadsheet_options <- list( ), spreadsheet_column_definition = list(editor = "input") ) + +# TODO: Helper function to set pagination +set_option_pagination <- function( + widget, + pagination = FALSE, + pagination_size = 10, + pagination_size_selector = FALSE, + pagination_add_row = c("page", "table"), + ...) { + return(widget) +} + +#' Set group by option +#' @inheritParams set_formatter_html +#' @inheritParams tabulator_options +#' @export +set_option_group_by <- function( + widget, + group_by, + group_start_open = TRUE, + group_toggle_element = "header", + ...) { + # return(widget) + options_update <- list( + groupBy = group_by, + groupStartOpen = group_start_open, + groupToggleElement = group_toggle_element, + ... + ) + modify_tabulator_options(widget, options_update) +} + +modify_tabulator_options <- function(widget, options) { + widget$x$options <- utils::modifyList( + widget$x$options, + keys_to_camel_case(compact(options)) + ) + return(widget) +} diff --git a/README.Rmd b/README.Rmd index b510347..453e196 100644 --- a/README.Rmd +++ b/README.Rmd @@ -17,22 +17,28 @@ knitr::opts_chunk$set( [![R-CMD-check](https://github.com/eodaGmbH/rtabulator/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/eodaGmbH/rtabulator/actions/workflows/R-CMD-check.yaml) +[![CRAN status](https://www.r-pkg.org/badges/version/rtabulator)](https://CRAN.R-project.org/package=rtabulator) +[![Tabulator](https://img.shields.io/badge/Tabulator-v6.2.5-blue.svg)](https://github.com/olifolkerd/tabulator/releases/tag/6.2.5) -The goal of rtabulator is to make it a breeze creating beautiful and reactive tables using -[Tabulator JS](https://tabulator.info/) +The goal of rtabulator is to make it a breeze creating beautiful and interactive tables in markdown documents and Shiny application using [Tabulator JS](https://tabulator.info/). ## Features -* Filters +* Filtering * Grouping -* Multiple column formatters (images, html, progress bar, ...) -* Multiple themes +* Editing +* Input validation +* History with undo and redo actions +* Pagination +* Layout +* Column formatters +* Column calculations * Multi column headers -* Spreadsheet mode supporting multiple sheets -* Cell editing supporting validation -* Downloads (json, csv, xlsx) -* Interactivity +* Packaged themes +* Spreadsheets supporting multiple sheets +* Download data +* Freeze data ## Installation diff --git a/README.md b/README.md index 83395c2..7906014 100644 --- a/README.md +++ b/README.md @@ -6,22 +6,31 @@ [![R-CMD-check](https://github.com/eodaGmbH/rtabulator/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/eodaGmbH/rtabulator/actions/workflows/R-CMD-check.yaml) +[![CRAN +status](https://www.r-pkg.org/badges/version/rtabulator)](https://CRAN.R-project.org/package=rtabulator) +[![Tabulator](https://img.shields.io/badge/Tabulator-v6.2.5-blue.svg)](https://github.com/olifolkerd/tabulator/releases/tag/6.2.5) The goal of rtabulator is to make it a breeze creating beautiful and -reactive tables using [Tabulator JS](https://tabulator.info/) +interactive tables in markdown documents and Shiny application using +[Tabulator JS](https://tabulator.info/). ## Features -- Filters +- Filtering - Grouping -- Multiple column formatters (images, html, progress bar, …) -- Multiple themes +- Editing +- Input validation +- History with undo and redo actions +- Pagination +- Layout +- Column formatters +- Column calculations - Multi column headers -- Spreadsheet mode supporting multiple sheets -- Cell editing supporting validation -- Downloads (json, csv, xlsx) -- Interactivity +- Packaged themes +- Spreadsheets supporting multiple sheets +- Download data +- Freeze data ## Installation diff --git a/_pkgdown.yml b/_pkgdown.yml index 88f9aea..768d2fd 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -9,9 +9,18 @@ reference: contents: - tabulator - tabulator_options - - set_column_editor + - set_option_group_by + + - title: Column Settings + desc: > + Functions to update the default column settings + contents: + - set_column_defaults + - set_editor - set_header_filter - set_multi_column_header + - set_tooltip + - for_each_col - title: Column Formatters desc: > @@ -19,6 +28,10 @@ reference: contents: - starts_with("set_formatter") + - title: Calculations + contents: + - set_calculation + - title: Shiny Integration contents: - rtabulator-shiny @@ -39,3 +52,6 @@ reference: - list_to_data_frame - create_columns + - title: Data Sets + contents: + - titanic diff --git a/examples/column_defaults.R b/examples/column_defaults.R new file mode 100644 index 0000000..8c1e950 --- /dev/null +++ b/examples/column_defaults.R @@ -0,0 +1,6 @@ +tabulator(iris, theme = "simple") |> + set_column_defaults( + header_filter = TRUE, + header_sort = FALSE, + tooltip = TRUE + ) diff --git a/examples/data_url.R b/examples/data_url.R new file mode 100644 index 0000000..52dd673 --- /dev/null +++ b/examples/data_url.R @@ -0,0 +1,12 @@ +data_url <- "https://raw.githubusercontent.com/eodaGmbH/rtabulator/main/data-raw/titanic.csv" + +tabulator( + data_url, + col_select = c("PassengerId", "Name", "Pclass", "Fare", "Survived"), + pagination = TRUE +) |> + set_formatter_star("Pclass") |> + set_formatter_tick_cross("Survived") |> + set_formatter_progress("Fare", legend = TRUE, legend_align = "right", hoz_align = "right") |> + set_calculation("Fare", func = "avg") |> + set_calculation("Pclass", func = "unique", pos = "bottom") diff --git a/examples/editors.R b/examples/editors.R new file mode 100644 index 0000000..f6c0e5f --- /dev/null +++ b/examples/editors.R @@ -0,0 +1,18 @@ +setup <- tabulator_options(edit_trigger_event = "click") + +tabulator(iris[, c(2, 5)], setup) |> + set_editor( + column = "Species", + editor = "list", + values_lookup = "active", + clearable = TRUE, + autocomplete = TRUE + ) |> + set_editor( + column = "Sepal_Width", + editor = "number", + min = 0, + max = 10, + step = 0.1, + validator = c("min:0", "max:10") + ) diff --git a/examples/for_each_col.R b/examples/for_each_col.R new file mode 100644 index 0000000..3685c14 --- /dev/null +++ b/examples/for_each_col.R @@ -0,0 +1,4 @@ +numeric_cols <- c("Sepal_Length", "Sepal_Width", "Petal_Length", "Petal_Width") + +tabulator(iris) |> + for_each_col(numeric_cols, .f = set_header_filter, type = "number", func = "<=") diff --git a/examples/misc/header_filter.R b/examples/misc/header_filter.R index 6661b5d..56622cb 100644 --- a/examples/misc/header_filter.R +++ b/examples/misc/header_filter.R @@ -5,4 +5,6 @@ data <- data.frame( ) tabulator(data) |> - set_header_filter() + set_header_filter("age", type = NULL, func = "<=", placeholder = "max age") |> + set_header_filter("first_name", placeholder = "Fran") |> + set_header_filter("last_name", type = "list") diff --git a/examples/misc/tooltip.R b/examples/misc/tooltip.R new file mode 100644 index 0000000..75d9300 --- /dev/null +++ b/examples/misc/tooltip.R @@ -0,0 +1,3 @@ +tabulator(airquality) |> + set_formatter_traffic_light("Ozone") |> + set_tooltip("Ozone") diff --git a/inst/htmlwidgets/libs/tabulator/LICENSE b/inst/htmlwidgets/libs/tabulator/LICENSE new file mode 100644 index 0000000..85fb142 --- /dev/null +++ b/inst/htmlwidgets/libs/tabulator/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015-2024 Oli Folkerd + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/man/for_each_col.Rd b/man/for_each_col.Rd new file mode 100644 index 0000000..13a27db --- /dev/null +++ b/man/for_each_col.Rd @@ -0,0 +1,27 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/columns.R +\name{for_each_col} +\alias{for_each_col} +\title{Apply a column setter function to multiple columns} +\usage{ +for_each_col(widget, columns = NULL, .f, ...) +} +\arguments{ +\item{widget}{(\code{\link{tabulator}}) A tabulator widget.} + +\item{columns}{(character vector): The columns the column setter function (\code{.f}) is applied to. +If set to \code{NULL} it is applied to all columns.} + +\item{.f}{(function): The column setter function that updates the column settings.} + +\item{...}{Arguments that are passed to \code{.f}.} +} +\description{ +Apply a column setter function to multiple columns +} +\examples{ +numeric_cols <- c("Sepal_Length", "Sepal_Width", "Petal_Length", "Petal_Width") + +tabulator(iris) |> + for_each_col(numeric_cols, .f = set_header_filter, type = "number", func = "<=") +} diff --git a/man/set_calculation.Rd b/man/set_calculation.Rd new file mode 100644 index 0000000..e398899 --- /dev/null +++ b/man/set_calculation.Rd @@ -0,0 +1,44 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/columns.R +\name{set_calculation} +\alias{set_calculation} +\title{Add a calculation to a column} +\usage{ +set_calculation( + widget, + column, + func = c("avg", "max", "min", "sum", "count", "unique"), + precision = 2, + pos = c("top", "bottom") +) +} +\arguments{ +\item{widget}{(\code{\link{tabulator}}) A tabulator widget.} + +\item{column}{(character): The column the \code{func} is applied to.} + +\item{func}{(character): The calculation function to be applied +to the values of the \code{column}.} + +\item{precision}{(integer) The number of decimals to display. +Set to \code{FALSE} to display all decimals.} + +\item{pos}{(character): Position at which calculated values are displayed.} +} +\description{ +Add a calculation to a column +} +\examples{ +data_url <- "https://raw.githubusercontent.com/eodaGmbH/rtabulator/main/data-raw/titanic.csv" + +tabulator( + data_url, + col_select = c("PassengerId", "Name", "Pclass", "Fare", "Survived"), + pagination = TRUE +) |> + set_formatter_star("Pclass") |> + set_formatter_tick_cross("Survived") |> + set_formatter_progress("Fare", legend = TRUE, legend_align = "right", hoz_align = "right") |> + set_calculation("Fare", func = "avg") |> + set_calculation("Pclass", func = "unique", pos = "bottom") +} diff --git a/man/set_column_defaults.Rd b/man/set_column_defaults.Rd new file mode 100644 index 0000000..ee1fe55 --- /dev/null +++ b/man/set_column_defaults.Rd @@ -0,0 +1,47 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/columns.R +\name{set_column_defaults} +\alias{set_column_defaults} +\title{Set column defaults} +\usage{ +set_column_defaults( + widget, + editor = FALSE, + header_filter = FALSE, + header_sort = TRUE, + tooltip = TRUE, + width = NULL, + ... +) +} +\arguments{ +\item{widget}{(\code{\link{tabulator}}) A tabulator widget.} + +\item{editor}{(character, bool): One of \code{"input"} or \code{"number"}. +If set to \code{FALSE} cells are not editable.} + +\item{header_filter}{(character, bool): One of \code{"input"} or \code{"number"}. +Set to \code{FALSE} to disable header filters.} + +\item{header_sort}{(bool): Whether to enable header sorting.} + +\item{tooltip}{(bool): Whether to show tooltips displaying the cell value.} + +\item{width}{(integer): Fixed width of columns.} + +\item{...}{Additional settings.} +} +\description{ +Set column defaults +} +\examples{ +tabulator(iris, theme = "simple") |> + set_column_defaults( + header_filter = TRUE, + header_sort = FALSE, + tooltip = TRUE + ) +} +\seealso{ +\url{https://tabulator.info/docs/6.2/columns#defaults} +} diff --git a/man/set_column_editor.Rd b/man/set_column_editor.Rd deleted file mode 100644 index c34ccfd..0000000 --- a/man/set_column_editor.Rd +++ /dev/null @@ -1,29 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/columns.R -\name{set_column_editor} -\alias{set_column_editor} -\title{Make columns editable} -\usage{ -set_column_editor(widget, columns, type = c("input", "number")) -} -\arguments{ -\item{widget}{(\code{\link{tabulator}}) A tabulator widget.} - -\item{columns}{(character vector): Columns the editor is applied to.} - -\item{type}{(character): Either \code{input} or \code{number}.} -} -\description{ -Make columns editable -} -\examples{ -data <- data.frame( - age = c(10, 20, 40), - first_name = c("Franz", "Ferdinand", "Julia"), - last_name = c("Young", "Bowie", "Blackey") -) - -tabulator(data, width = 500) |> - set_column_editor(c("first_name", "last_name")) |> - set_column_editor("age", type = "number") -} diff --git a/man/set_editor.Rd b/man/set_editor.Rd new file mode 100644 index 0000000..a527cb3 --- /dev/null +++ b/man/set_editor.Rd @@ -0,0 +1,53 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/columns.R +\name{set_editor} +\alias{set_editor} +\title{Set editor} +\usage{ +set_editor( + widget, + column, + editor = c("input", "textarea", "number", "range", "tickCross", "star", "progress", + "date", "time", "datetime", "list"), + validator = NULL, + ... +) +} +\arguments{ +\item{widget}{(\code{\link{tabulator}}) A tabulator widget.} + +\item{column}{(character): The column the formatter is applied to.} + +\item{editor}{(character): The editor type.} + +\item{validator}{(character vector): One or more validators to validate user input.} + +\item{...}{Optional editor parameters depending on the selected editor.} +} +\description{ +Set editor +} +\examples{ +setup <- tabulator_options(edit_trigger_event = "click") + +tabulator(iris[, c(2, 5)], setup) |> + set_editor( + column = "Species", + editor = "list", + values_lookup = "active", + clearable = TRUE, + autocomplete = TRUE + ) |> + set_editor( + column = "Sepal_Width", + editor = "number", + min = 0, + max = 10, + step = 0.1, + validator = c("min:0", "max:10") + ) +} +\seealso{ +\url{https://tabulator.info/docs/6.2/edit} for available editors + \url{https://tabulator.info/docs/6.2/validate} for available validators. +} diff --git a/man/set_formatter_star.Rd b/man/set_formatter_star.Rd index a605529..638d32f 100644 --- a/man/set_formatter_star.Rd +++ b/man/set_formatter_star.Rd @@ -4,14 +4,15 @@ \alias{set_formatter_star} \title{Star Rating Formatter} \usage{ -set_formatter_star(widget, column, number_of_stars, hoz_align = "center") +set_formatter_star(widget, column, number_of_stars = NA, hoz_align = "center") } \arguments{ \item{widget}{(\code{\link{tabulator}}) A tabulator widget.} \item{column}{(character): The column the formatter is applied to.} -\item{number_of_stars}{The maximum number of stars to be displayed.} +\item{number_of_stars}{The maximum number of stars to be displayed. +If set to \code{NA}, the maximum value of the column is used.} \item{hoz_align}{(character): The horizontal alignment of the column.} } diff --git a/man/set_header_filter.Rd b/man/set_header_filter.Rd index d8bd8b5..332b61a 100644 --- a/man/set_header_filter.Rd +++ b/man/set_header_filter.Rd @@ -2,18 +2,35 @@ % Please edit documentation in R/columns.R \name{set_header_filter} \alias{set_header_filter} -\title{Add header filter} +\title{Add header filter to column} \usage{ -set_header_filter(widget, columns = NULL) +set_header_filter( + widget, + column, + type = c("input", "number", "list", "tickCross"), + func = c("like", "=", ">", ">=", "<", "<="), + values_lookup = TRUE, + clearable = TRUE, + placeholder = NULL +) } \arguments{ \item{widget}{(\code{\link{tabulator}}) A tabulator widget.} -\item{columns}{(character vector): Columns the editor is applied to. -If set to \code{NULL}, the editor is applied to all columns.} +\item{column}{(character): The column the formatter is applied to.} + +\item{type}{(character): The type of the filter.} + +\item{func}{(character): The filter function.} + +\item{values_lookup}{(bool): Whether to use unique column values for the list filter.} + +\item{clearable}{(bool): Whether to display a cross to clear the filter.} + +\item{placeholder}{(character): Text that is displayed when no filter is set.} } \description{ -Add header filter +Add header filter to column } \examples{ data <- data.frame( @@ -23,5 +40,7 @@ data <- data.frame( ) tabulator(data) |> - set_header_filter() + set_header_filter("age", type = NULL, func = "<=", placeholder = "max age") |> + set_header_filter("first_name", placeholder = "Fran") |> + set_header_filter("last_name", type = "list") } diff --git a/man/set_option_group_by.Rd b/man/set_option_group_by.Rd new file mode 100644 index 0000000..888a0b4 --- /dev/null +++ b/man/set_option_group_by.Rd @@ -0,0 +1,31 @@ +% 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} +\usage{ +set_option_group_by( + widget, + group_by, + group_start_open = TRUE, + group_toggle_element = "header", + ... +) +} +\arguments{ +\item{widget}{(\code{\link{tabulator}}) A tabulator widget.} + +\item{group_by}{(character vector): Field to group rows by. Pass multiple values +for multi level grouping.} + +\item{group_start_open}{(bool vector): Open state of groups when grouping is enabled. +The length of the vector depends on the number of levels set with \code{group_by}.} + +\item{group_toggle_element}{(character, bool): One of \code{arrow} or \code{header}. +Set to \code{FALSE} to disable toggling at all.} + +\item{...}{Further options.} +} +\description{ +Set group by option +} diff --git a/man/set_tooltip.Rd b/man/set_tooltip.Rd new file mode 100644 index 0000000..a1b78b9 --- /dev/null +++ b/man/set_tooltip.Rd @@ -0,0 +1,21 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/columns.R +\name{set_tooltip} +\alias{set_tooltip} +\title{Add tooltip to column} +\usage{ +set_tooltip(widget, column) +} +\arguments{ +\item{widget}{(\code{\link{tabulator}}) A tabulator widget.} + +\item{column}{(character): The column the formatter is applied to.} +} +\description{ +Add tooltip to column +} +\examples{ +tabulator(airquality) |> + set_formatter_traffic_light("Ozone") |> + set_tooltip("Ozone") +} diff --git a/man/tabulator.Rd b/man/tabulator.Rd index b065b50..d292fba 100644 --- a/man/tabulator.Rd +++ b/man/tabulator.Rd @@ -11,6 +11,7 @@ tabulator( sheetjs = FALSE, theme = c("default", "midnight", "modern", "simple", "site", "bootstrap3", "bootstrap4", "bootstrap5", "bulma", "materialize", "semanticui"), + col_select = NULL, width = NULL, height = NULL, element_id = NULL, @@ -30,6 +31,9 @@ which is needed for xlsx downloads.} \item{theme}{(character): Theme to apply to the table.} +\item{col_select}{(character vector) Columns to select. +Passed to \code{\link[readr]{read_csv}} if \code{data} is a file name.} + \item{width}{Width of the widget.} \item{height}{Height of the widget.} diff --git a/man/tabulator_options.Rd b/man/tabulator_options.Rd index 010a369..e8a1c53 100644 --- a/man/tabulator_options.Rd +++ b/man/tabulator_options.Rd @@ -19,6 +19,8 @@ tabulator_options( frozen_rows = NULL, index = "id", group_by = NULL, + group_start_open = TRUE, + group_toggle_element = NULL, edit_trigger_event = c("dblclick", "click", "focus"), selectable_rows = "highlight", pagination = FALSE, @@ -63,7 +65,14 @@ the width of the Tabulator element.} \item{index}{(character): Field to be used as the unique index for each row.} -\item{group_by}{(character): Field to group rows by.} +\item{group_by}{(character vector): Field to group rows by. Pass multiple values +for multi level grouping.} + +\item{group_start_open}{(bool vector): Open state of groups when grouping is enabled. +The length of the vector depends on the number of levels set with \code{group_by}.} + +\item{group_toggle_element}{(character, bool): One of \code{arrow} or \code{header}. +Set to \code{FALSE} to disable toggling at all.} \item{edit_trigger_event}{(character): Event that triggers a cell edit.} diff --git a/man/titanic.Rd b/man/titanic.Rd new file mode 100644 index 0000000..6fee7de --- /dev/null +++ b/man/titanic.Rd @@ -0,0 +1,14 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/data.R +\name{titanic} +\alias{titanic} +\title{Titanic data set} +\usage{ +titanic(col_select = NULL) +} +\arguments{ +\item{col_select}{(character vector): Columns to select.} +} +\description{ +Titanic data set +} diff --git a/vignettes/articles/rtabulator.Rmd b/vignettes/articles/rtabulator.Rmd index b55b265..f7f4536 100644 --- a/vignettes/articles/rtabulator.Rmd +++ b/vignettes/articles/rtabulator.Rmd @@ -25,13 +25,35 @@ To render a table just pass a data frame to `tabulator()`: 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_. +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: + +```{r} +data_url <- "https://raw.githubusercontent.com/eodaGmbH/rtabulator/main/data-raw/titanic.csv" + +tabulator( + data_url, + col_select = c("PassengerId", "Name", "Pclass", "Fare", "Survived") +) +``` ## Setup Options With `tabulator_options()` you can customize your table (or spreadsheet): +```{r} +setup <- tabulator_options( + row_height = 50, + selectable_rows = FALSE, + edit_trigger_event = "click" +) + +tabulator(iris, setup, editable = TRUE) +``` + +## Pagination + ```{r} setup <- tabulator_options( pagination = TRUE, @@ -44,12 +66,31 @@ tabulator(USArrests, setup) ## Column Formatters -To customize your columns, the easiest way is to use the `set_formatter_*` functions like `set_formatter_progress()` and others: +To customize your columns, the easiest way is to use the `set_formatter_*()` functions: ```{r} tabulator(airquality) |> set_formatter_progress("Temp", legend = TRUE, legend_align = "left") |> - set_formatter_traffic_light("Ozone") + set_formatter_traffic_light("Ozone") |> + set_tooltip("Ozone") +``` + +With `for_each_col()` you can apply a formatter to multiple columns: + +```{r} +numeric_cols <- c("Sepal_Length", "Sepal_Width", "Petal_Length", "Petal_Width") + +tabulator(iris) |> + for_each_col( + numeric_cols, + set_formatter_progress, + legend = TRUE, + legend_align = "left", + min = 0, + max = 10, + color = c("yellow", "orange", "green") + ) |> + for_each_col(numeric_cols, set_tooltip) ``` ## Multi Column headers @@ -63,9 +104,93 @@ headers <- list( ) tabulator(iris) |> + set_header_filter("Species", "list", placeholder = "Select Species") |> set_multi_column_header(headers) ``` +*** + +**Note** + +If further functions update the column definitions, `set_multi_column_header()` must be the last one. Therefore, in the example above `set_header_filter()` is called before we set the multi column header. + +*** + +## Groupings + +```{r} +setup <- tabulator_options( + group_by = c("Pclass"), + group_start_open = FALSE, + group_toggle_element = "header" +) + +titanic_df <- titanic(c("Pclass", "Sex", "Age", "Survived")) + +tabulator(titanic_df, setup) |> + set_formatter_traffic_light("Survived", color = c("red", "green")) +``` + +Multi level grouping is done by passing a vector as `group_by` parameter: + +```{r} +setup <- tabulator_options( + group_by = c("Sex", "Pclass"), + group_start_open = c(TRUE, FALSE) +) + +tabulator(titanic_df, setup) +``` + +*** + +**Note** + +You can also use `set_option_group_by()` to set the group by options. + +*** + +## Calculations + +With `set_calculation()` you can add calculations to the top or bottom of columns: + +```{r} +tabulator(iris[4:5]) |> + set_calculation("Petal_Width", "avg", pos = "top") |> + set_calculation("Petal_Width", "max", precision = 1, pos = "bottom") +``` + +## Editors + +Set `editable = TRUE` to make all columns of the table editable. In this case, the editor for numeric columns is set to `number` and all others to `input`. + +```{r} +setup <- tabulator_options(edit_trigger_event = "click") + +tabulator(iris, setup, editable = TRUE) +``` + +To customize editor settings and validate user input use `set_editor()`: + +```{r} +tabulator(iris[, c(2, 5)], setup) |> + set_editor( + column = "Species", + editor = "list", + values_lookup = "active", + clearable = TRUE, + autocomplete = TRUE + ) |> + set_editor( + column = "Sepal_Width", + editor = "number", + min = 0, + max = 10, + step = 0.1, + validator = c("min:0", "max:10") + ) +``` + ## Spreadsheets To create an empty spreadsheet just pass an empty list as `data` parameter and `spreadsheet = TRUE` to `tabulator()`: @@ -90,7 +215,7 @@ sheets <- list( spreadsheet_def(title = "Lee", data = spreadsheet_data), spreadsheet_def(title = "Morgan", data = list()) # Empty spreadsheet ) -setup = tabulator_options( +setup <- tabulator_options( spreadsheet = TRUE, spreadsheet_sheets = sheets, spreadsheet_sheet_tabs = TRUE,