From 1f4e6e826f8004b20f090d8ab3a7ce10dee6eb1f Mon Sep 17 00:00:00 2001 From: osenan Date: Tue, 5 May 2026 02:12:57 +0200 Subject: [PATCH 01/12] docs: add new vignette for choices or selections --- .../teal-picks-choices-and-selections.Rmd | 226 ++++++++++++++++++ 1 file changed, 226 insertions(+) create mode 100644 vignettes/teal-picks-choices-and-selections.Rmd diff --git a/vignettes/teal-picks-choices-and-selections.Rmd b/vignettes/teal-picks-choices-and-selections.Rmd new file mode 100644 index 0000000..714b91d --- /dev/null +++ b/vignettes/teal-picks-choices-and-selections.Rmd @@ -0,0 +1,226 @@ +--- +title: "Choices and selections in teal.picks" +author: "NEST CoreDev" +date: "`r Sys.Date()`" +vignette: > + %\VignetteIndexEntry{Choices and selections in teal.picks} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +output: + rmarkdown::html_vignette: + toc: true +--- + +```{r setup, include = FALSE} +knitr::opts_chunk$set(comment = NA) +``` + +## Overview + +Every `picks()` object is built from three kinds of building blocks: `datasets()`, `variables()`, +and `values()`. Each one carries two core arguments: + +- `choices` — the full set of options the app user can pick from. +- `selected` — the subset that is pre-selected when the app starts. + +``` +picks( + datasets(choices = , selected = ), + variables(choices = , selected = ), + values(choices = , selected = ) +) +``` + +Choices and selections can be expressed in three ways: + +| Approach | Works with | +|---|---| +| Explicit — character vector, integer index, or numeric range | `datasets()`, `variables()`, `values()` | +| `tidyselect` helpers — `everything()`, `starts_with()`, `where()`, … | `datasets()`, `variables()` only | +| Function — an R function applied at runtime to the data | `datasets()`, `variables()`, `values()` | + +The sections below walk through each approach with runnable examples. + +```{r data, message = FALSE} +library(teal.data) +library(teal.picks) + +data <- teal_data() +data <- within(data, { + ADSL <- data.frame( + USUBJID = sprintf("S%03d", 1:10), + AGE = sample(40:75, 10, replace = TRUE), + SEX = rep(c("M", "F"), 5), + ARM = rep(c("A", "B"), 5), + stringsAsFactors = FALSE + ) + ADLB <- data.frame( + USUBJID = rep(sprintf("S%03d", 1:10), each = 3), + PARAM = rep(c("ALT", "AST", "CRP"), 10), + AVAL = round(rnorm(30, mean = 40, sd = 8), 1), + stringsAsFactors = FALSE + ) +}) + +join_keys(data) <- join_keys( + teal.data::join_key("ADSL", "ADLB", keys = "USUBJID") +) +``` + +--- + +## 1. Explicit choices + +Pass a character vector to `choices` to enumerate options exactly. Use `selected` to set the +default. Integer indices work too (for example `selected = 1L` means the first element of +`choices`). + +```{r explicit} +# Datasets — user may switch between ADSL and ADLB; ADSL is the default +p_datasets <- picks( + datasets( + choices = c("ADSL", "ADLB"), + selected = "ADSL" + ) +) + +# Variables — only a named subset is offered; first column pre-selected +p_variables <- picks( + datasets(choices = "ADSL", selected = "ADSL"), + variables( + choices = c("AGE", "SEX", "ARM"), + selected = "AGE", + multiple = FALSE + ) +) + +# Values — categorical filter; two levels pre-selected +p_values <- picks( + datasets(choices = "ADSL", selected = "ADSL"), + variables(choices = "SEX", selected = "SEX", multiple = FALSE), + values( + choices = c("M", "F"), + selected = "F" + ) +) + +resolver(x = p_datasets, data = as.list(data)) +resolver(x = p_variables, data = as.list(data)) +resolver(x = p_values, data = as.list(data)) +``` + +--- + +## 2. `tidyselect` helpers + +`tidyselect` predicates let `choices` and `selected` adapt to the actual data at runtime instead +of being hard-coded. This is supported for `datasets()` and `variables()`. + +Commonly used helpers: + +- `tidyselect::everything()` — all items +- `tidyselect::starts_with()` / `tidyselect::ends_with()` / `tidyselect::contains()` — pattern matching +- `tidyselect::matches()` — regex matching +- `tidyselect::where(predicate)` — columns satisfying a predicate function +- `tidyselect::all_of()` / `tidyselect::any_of()` — vector-based selection (error-safe or silent) +- Integer indices such as `1L`, `1L:3L` — select by position + +> Note: `tidyselect` is not supported by `values()`. Use explicit vectors or a function +> there instead (see [Section 3](#functions)). + +```{r tidyselect} +# Datasets — offer any data.frame in the teal_data object +p_any_dataset <- picks( + datasets( + choices = tidyselect::where(is.data.frame), + selected = 1L # first dataset by default + ) +) + +# Variables — all numeric columns; first one pre-selected +p_numeric_vars <- picks( + datasets(choices = "ADSL", selected = "ADSL"), + variables( + choices = tidyselect::where(is.numeric), + selected = 1L, + multiple = FALSE + ) +) + +# Variables — columns whose names start with "A"; first two pre-selected +p_a_prefix <- picks( + datasets(choices = "ADSL", selected = "ADSL"), + variables( + choices = tidyselect::starts_with("A"), + selected = 1L:2L, + multiple = TRUE + ) +) + +resolver(x = p_any_dataset, data = as.list(data)) +resolver(x = p_numeric_vars, data = as.list(data)) +resolver(x = p_a_prefix, data = as.list(data)) +``` + +--- + +## 3. Functions {#functions} + +You can pass a plain R function as `choices` or `selected`. The function receives the relevant +context object (the current dataset for `datasets()` and `variables()`, the current column vector +for `values()`) and must return the subset to use. This is the only runtime-dynamic approach +supported by `values()`. + +```{r functions} +# Variables — use the package helper is_categorical() as a column predicate. +# Without "des-delayed", the resolver calls it via vapply(data, fn, logical(1)), +# so it must accept one column and return a single logical value — which is_categorical() does. +p_cat_vars <- picks( + datasets(choices = "ADSL", selected = "ADSL"), + variables( + choices = is_categorical(), + selected = 1L, + multiple = TRUE + ) +) + +# Values — select only even ages from the AGE column. +# Functions passed to values() must carry the "des-delayed" class so the resolver +# calls them with the column vector rather than treating them as a column predicate. +even_vals <- function(x) sort(unique(x[x %% 2 == 0])) +class(even_vals) <- append(class(even_vals), "des-delayed") + +p_even_ages <- picks( + datasets(choices = "ADSL", selected = "ADSL"), + variables(choices = "AGE", selected = "AGE", multiple = FALSE), + values( + choices = even_vals, + selected = even_vals + ) +) + +resolver(x = p_cat_vars, data = as.list(data)) +resolver(x = p_even_ages, data = as.list(data)) +``` + +--- + +## Summary + +| | Explicit | `tidyselect` | Function | +|---|:---:|:---:|:---:| +| `datasets()` | yes | yes | yes | +| `variables()` | yes | yes | yes | +| `values()` | yes | **no** | yes | + +Use **explicit** choices when the set of options is fixed and known at app-development time. +Use **`tidyselect`** when you want the choices to adapt to the shape of the data without writing +a custom function. Use **functions** when the logic is more involved, or when you need runtime +behaviour for `values()`. + +## See also + +- `?picks` — full reference for `picks()`, `datasets()`, `variables()`, and `values()`. +- `?tidyselectors` — package-specific tidyselect helpers such as `is_categorical()`. +- `vignette("teal-picks-in-teal", package = "teal.picks")` — wiring `picks` into a `teal` module. +- `vignette("teal-picks-standalone-shiny", package = "teal.picks")` — using `picks` in plain Shiny. From 4dfea9be362c47b88f06073ed26a6559139821e1 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 5 May 2026 00:15:27 +0000 Subject: [PATCH 02/12] [skip style] [skip vbump] Restyle files --- .../teal-picks-choices-and-selections.Rmd | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/vignettes/teal-picks-choices-and-selections.Rmd b/vignettes/teal-picks-choices-and-selections.Rmd index 714b91d..c0042ea 100644 --- a/vignettes/teal-picks-choices-and-selections.Rmd +++ b/vignettes/teal-picks-choices-and-selections.Rmd @@ -48,16 +48,16 @@ library(teal.picks) data <- teal_data() data <- within(data, { ADSL <- data.frame( - USUBJID = sprintf("S%03d", 1:10), - AGE = sample(40:75, 10, replace = TRUE), - SEX = rep(c("M", "F"), 5), - ARM = rep(c("A", "B"), 5), + USUBJID = sprintf("S%03d", 1:10), + AGE = sample(40:75, 10, replace = TRUE), + SEX = rep(c("M", "F"), 5), + ARM = rep(c("A", "B"), 5), stringsAsFactors = FALSE ) ADLB <- data.frame( USUBJID = rep(sprintf("S%03d", 1:10), each = 3), - PARAM = rep(c("ALT", "AST", "CRP"), 10), - AVAL = round(rnorm(30, mean = 40, sd = 8), 1), + PARAM = rep(c("ALT", "AST", "CRP"), 10), + AVAL = round(rnorm(30, mean = 40, sd = 8), 1), stringsAsFactors = FALSE ) }) @@ -133,7 +133,7 @@ Commonly used helpers: p_any_dataset <- picks( datasets( choices = tidyselect::where(is.data.frame), - selected = 1L # first dataset by default + selected = 1L # first dataset by default ) ) @@ -199,8 +199,8 @@ p_even_ages <- picks( ) ) -resolver(x = p_cat_vars, data = as.list(data)) -resolver(x = p_even_ages, data = as.list(data)) +resolver(x = p_cat_vars, data = as.list(data)) +resolver(x = p_even_ages, data = as.list(data)) ``` --- From 5dc6fb48c54079a9522332c438706a16bd9f1f14 Mon Sep 17 00:00:00 2001 From: osenan Date: Tue, 5 May 2026 02:19:28 +0200 Subject: [PATCH 03/12] chore: fix spelling --- inst/WORDLIST | 2 ++ vignettes/teal-picks-choices-and-selections.Rmd | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/inst/WORDLIST b/inst/WORDLIST index cba3af1..1f89975 100644 --- a/inst/WORDLIST +++ b/inst/WORDLIST @@ -3,7 +3,9 @@ CDISC Forkers UI mimicks +pre reactives +runnable schemas stratifiers tidyselect diff --git a/vignettes/teal-picks-choices-and-selections.Rmd b/vignettes/teal-picks-choices-and-selections.Rmd index c0042ea..6c6562a 100644 --- a/vignettes/teal-picks-choices-and-selections.Rmd +++ b/vignettes/teal-picks-choices-and-selections.Rmd @@ -216,7 +216,7 @@ resolver(x = p_even_ages, data = as.list(data)) Use **explicit** choices when the set of options is fixed and known at app-development time. Use **`tidyselect`** when you want the choices to adapt to the shape of the data without writing a custom function. Use **functions** when the logic is more involved, or when you need runtime -behaviour for `values()`. +behavior for `values()`. ## See also From 2e4d70543825678f3c587fdcc7815a8f9343460e Mon Sep 17 00:00:00 2001 From: osenan Date: Tue, 5 May 2026 17:50:18 +0200 Subject: [PATCH 04/12] docs: modify vignettes based on review feedback --- .../teal-picks-choices-and-selections.Rmd | 226 ------------------ vignettes/teal-picks-in-teal.Rmd | 196 +++++++++++++-- 2 files changed, 182 insertions(+), 240 deletions(-) delete mode 100644 vignettes/teal-picks-choices-and-selections.Rmd diff --git a/vignettes/teal-picks-choices-and-selections.Rmd b/vignettes/teal-picks-choices-and-selections.Rmd deleted file mode 100644 index 6c6562a..0000000 --- a/vignettes/teal-picks-choices-and-selections.Rmd +++ /dev/null @@ -1,226 +0,0 @@ ---- -title: "Choices and selections in teal.picks" -author: "NEST CoreDev" -date: "`r Sys.Date()`" -vignette: > - %\VignetteIndexEntry{Choices and selections in teal.picks} - %\VignetteEngine{knitr::rmarkdown} - %\VignetteEncoding{UTF-8} -output: - rmarkdown::html_vignette: - toc: true ---- - -```{r setup, include = FALSE} -knitr::opts_chunk$set(comment = NA) -``` - -## Overview - -Every `picks()` object is built from three kinds of building blocks: `datasets()`, `variables()`, -and `values()`. Each one carries two core arguments: - -- `choices` — the full set of options the app user can pick from. -- `selected` — the subset that is pre-selected when the app starts. - -``` -picks( - datasets(choices = , selected = ), - variables(choices = , selected = ), - values(choices = , selected = ) -) -``` - -Choices and selections can be expressed in three ways: - -| Approach | Works with | -|---|---| -| Explicit — character vector, integer index, or numeric range | `datasets()`, `variables()`, `values()` | -| `tidyselect` helpers — `everything()`, `starts_with()`, `where()`, … | `datasets()`, `variables()` only | -| Function — an R function applied at runtime to the data | `datasets()`, `variables()`, `values()` | - -The sections below walk through each approach with runnable examples. - -```{r data, message = FALSE} -library(teal.data) -library(teal.picks) - -data <- teal_data() -data <- within(data, { - ADSL <- data.frame( - USUBJID = sprintf("S%03d", 1:10), - AGE = sample(40:75, 10, replace = TRUE), - SEX = rep(c("M", "F"), 5), - ARM = rep(c("A", "B"), 5), - stringsAsFactors = FALSE - ) - ADLB <- data.frame( - USUBJID = rep(sprintf("S%03d", 1:10), each = 3), - PARAM = rep(c("ALT", "AST", "CRP"), 10), - AVAL = round(rnorm(30, mean = 40, sd = 8), 1), - stringsAsFactors = FALSE - ) -}) - -join_keys(data) <- join_keys( - teal.data::join_key("ADSL", "ADLB", keys = "USUBJID") -) -``` - ---- - -## 1. Explicit choices - -Pass a character vector to `choices` to enumerate options exactly. Use `selected` to set the -default. Integer indices work too (for example `selected = 1L` means the first element of -`choices`). - -```{r explicit} -# Datasets — user may switch between ADSL and ADLB; ADSL is the default -p_datasets <- picks( - datasets( - choices = c("ADSL", "ADLB"), - selected = "ADSL" - ) -) - -# Variables — only a named subset is offered; first column pre-selected -p_variables <- picks( - datasets(choices = "ADSL", selected = "ADSL"), - variables( - choices = c("AGE", "SEX", "ARM"), - selected = "AGE", - multiple = FALSE - ) -) - -# Values — categorical filter; two levels pre-selected -p_values <- picks( - datasets(choices = "ADSL", selected = "ADSL"), - variables(choices = "SEX", selected = "SEX", multiple = FALSE), - values( - choices = c("M", "F"), - selected = "F" - ) -) - -resolver(x = p_datasets, data = as.list(data)) -resolver(x = p_variables, data = as.list(data)) -resolver(x = p_values, data = as.list(data)) -``` - ---- - -## 2. `tidyselect` helpers - -`tidyselect` predicates let `choices` and `selected` adapt to the actual data at runtime instead -of being hard-coded. This is supported for `datasets()` and `variables()`. - -Commonly used helpers: - -- `tidyselect::everything()` — all items -- `tidyselect::starts_with()` / `tidyselect::ends_with()` / `tidyselect::contains()` — pattern matching -- `tidyselect::matches()` — regex matching -- `tidyselect::where(predicate)` — columns satisfying a predicate function -- `tidyselect::all_of()` / `tidyselect::any_of()` — vector-based selection (error-safe or silent) -- Integer indices such as `1L`, `1L:3L` — select by position - -> Note: `tidyselect` is not supported by `values()`. Use explicit vectors or a function -> there instead (see [Section 3](#functions)). - -```{r tidyselect} -# Datasets — offer any data.frame in the teal_data object -p_any_dataset <- picks( - datasets( - choices = tidyselect::where(is.data.frame), - selected = 1L # first dataset by default - ) -) - -# Variables — all numeric columns; first one pre-selected -p_numeric_vars <- picks( - datasets(choices = "ADSL", selected = "ADSL"), - variables( - choices = tidyselect::where(is.numeric), - selected = 1L, - multiple = FALSE - ) -) - -# Variables — columns whose names start with "A"; first two pre-selected -p_a_prefix <- picks( - datasets(choices = "ADSL", selected = "ADSL"), - variables( - choices = tidyselect::starts_with("A"), - selected = 1L:2L, - multiple = TRUE - ) -) - -resolver(x = p_any_dataset, data = as.list(data)) -resolver(x = p_numeric_vars, data = as.list(data)) -resolver(x = p_a_prefix, data = as.list(data)) -``` - ---- - -## 3. Functions {#functions} - -You can pass a plain R function as `choices` or `selected`. The function receives the relevant -context object (the current dataset for `datasets()` and `variables()`, the current column vector -for `values()`) and must return the subset to use. This is the only runtime-dynamic approach -supported by `values()`. - -```{r functions} -# Variables — use the package helper is_categorical() as a column predicate. -# Without "des-delayed", the resolver calls it via vapply(data, fn, logical(1)), -# so it must accept one column and return a single logical value — which is_categorical() does. -p_cat_vars <- picks( - datasets(choices = "ADSL", selected = "ADSL"), - variables( - choices = is_categorical(), - selected = 1L, - multiple = TRUE - ) -) - -# Values — select only even ages from the AGE column. -# Functions passed to values() must carry the "des-delayed" class so the resolver -# calls them with the column vector rather than treating them as a column predicate. -even_vals <- function(x) sort(unique(x[x %% 2 == 0])) -class(even_vals) <- append(class(even_vals), "des-delayed") - -p_even_ages <- picks( - datasets(choices = "ADSL", selected = "ADSL"), - variables(choices = "AGE", selected = "AGE", multiple = FALSE), - values( - choices = even_vals, - selected = even_vals - ) -) - -resolver(x = p_cat_vars, data = as.list(data)) -resolver(x = p_even_ages, data = as.list(data)) -``` - ---- - -## Summary - -| | Explicit | `tidyselect` | Function | -|---|:---:|:---:|:---:| -| `datasets()` | yes | yes | yes | -| `variables()` | yes | yes | yes | -| `values()` | yes | **no** | yes | - -Use **explicit** choices when the set of options is fixed and known at app-development time. -Use **`tidyselect`** when you want the choices to adapt to the shape of the data without writing -a custom function. Use **functions** when the logic is more involved, or when you need runtime -behavior for `values()`. - -## See also - -- `?picks` — full reference for `picks()`, `datasets()`, `variables()`, and `values()`. -- `?tidyselectors` — package-specific tidyselect helpers such as `is_categorical()`. -- `vignette("teal-picks-in-teal", package = "teal.picks")` — wiring `picks` into a `teal` module. -- `vignette("teal-picks-standalone-shiny", package = "teal.picks")` — using `picks` in plain Shiny. diff --git a/vignettes/teal-picks-in-teal.Rmd b/vignettes/teal-picks-in-teal.Rmd index 8d14750..059dad4 100644 --- a/vignettes/teal-picks-in-teal.Rmd +++ b/vignettes/teal-picks-in-teal.Rmd @@ -34,21 +34,11 @@ library(teal.picks) data <- teal_data() data <- within(data, { - ADSL <- data.frame( - USUBJID = sprintf("S%03d", 1:12), - AGE = sample(40:75, 12, replace = TRUE), - SEX = rep(c("M", "F"), 6), - stringsAsFactors = FALSE - ) - ADLB <- data.frame( - USUBJID = rep(sprintf("S%03d", 1:12), each = 4), - PARAM = rep(c("ALT", "AST", "CRP", "GLU"), 12), - AVAL = round(rnorm(48, mean = 40, sd = 8), 1), - stringsAsFactors = FALSE - ) + ADSL <- teal.data::rADSL + ADLB <- teal.data::rADLB }) -join_keys(data) <- join_keys(teal.data::join_key("ADSL", "ADLB", keys = "USUBJID")) +join_keys(data) <- teal.data::default_cdisc_join_keys[c("ADSL", "ADLB")] ``` ### Choose a dataset @@ -105,7 +95,169 @@ picks_datasets_variables_values <- list( -### Several columns at once +### Define choices and selections + +Each `picks()` element has `choices` and `selected`. You can define them in four ways: + +| Approach | Works with | +|---|---| +| Default behavior | `variables()`, `values()`, and `datasets()` (`selected` only) | +| Static — character vector, integer index, or numeric range | `datasets()`, `variables()`, `values()` | +| `tidyselect` helpers — `everything()`, `starts_with()`, `where()`, … | `datasets()`, `variables()` only | +| Function — an R function applied at runtime to the data | `datasets()`, `variables()`, `values()` | + +The sections below walk through each approach with runnable examples. + +#### Defaults +Defaults depend on the slot type. +For `datasets()`, there is no default for `choices`; define at least one dataset unless `check_no_dataset = FALSE`. +For `variables()`, the default `choices` is all variables in the selected dataset. +For `values()`, the default `choices` is all values of the selected variable. +For `selected`, the default is the first available choice, or all choices when `multiple = TRUE`. + +```{r defaults} +picks( + datasets(choices = "ADSL", selected = "ADSL"), + variables() +) + +picks( + datasets(choices = "ADSL", selected = "ADSL"), + variables(choices = "SEX", selected = "SEX", multiple = FALSE), + values() +) +``` + +#### Static choices + +Pass a character vector to `choices` to enumerate options exactly. Use `selected` to set the +default. Integer indices work too (for example `selected = 1L` means the first element of +`choices`). + +```{r static} +# Datasets — user may switch between ADSL and ADLB; ADSL is the default +p_datasets <- picks( + datasets( + choices = c("ADSL", "ADLB"), + selected = "ADSL" + ) +) + +# Variables — only a named subset is offered; first column pre-selected +p_variables <- picks( + datasets(choices = "ADSL", selected = "ADSL"), + variables( + choices = c("AGE", "SEX", "ARM"), + selected = "AGE", + multiple = FALSE + ) +) + +# Values — categorical filter; two levels pre-selected +p_values <- picks( + datasets(choices = "ADSL", selected = "ADSL"), + variables(choices = "SEX", selected = "SEX", multiple = FALSE), + values( + choices = c("M", "F"), + selected = "F" + ) +) + +p_datasets +p_variables +p_values +``` + +#### `tidyselect` helpers + +`tidyselect` predicates let `choices` and `selected` adapt to the actual data at runtime instead +of being hard-coded. This is supported for `datasets()` and `variables()`. + +Commonly used helpers: + +- `tidyselect::everything()` — all items +- `tidyselect::starts_with()` / `tidyselect::ends_with()` / `tidyselect::contains()` — pattern matching +- `tidyselect::matches()` — regex matching +- `tidyselect::where(predicate)` — columns satisfying a predicate function +- `tidyselect::all_of()` / `tidyselect::any_of()` — vector-based selection (error-safe or silent) +- Integer indices such as `1L`, `1L:3L` — select by position + +> Note: `tidyselect` is not supported by `values()`. Use explicit vectors or a function +> there instead (see [Functions](#functions)). + +```{r tidyselect} +# Datasets — offer any data.frame in the teal_data object +p_any_dataset <- picks( + datasets( + choices = tidyselect::where(is.data.frame), + selected = 1L # first dataset by default + ) +) + +# Variables — all numeric columns; first one pre-selected +p_numeric_vars <- picks( + datasets(choices = "ADSL", selected = "ADSL"), + variables( + choices = tidyselect::where(is.numeric), + selected = 1L, + multiple = FALSE + ) +) + +# Variables — columns whose names start with "A"; first two pre-selected +p_a_prefix <- picks( + datasets(choices = "ADSL", selected = "ADSL"), + variables( + choices = tidyselect::starts_with("A"), + selected = 1L:2L, + multiple = TRUE + ) +) + +p_any_dataset +p_numeric_vars +p_a_prefix +``` + +#### Functions {#functions} + +You can pass a plain R function as `choices` or `selected`. The function receives the relevant +context object (the current dataset for `datasets()` and `variables()`, the current column vector +for `values()`) and must return the subset to use. This is the only runtime-dynamic approach +supported by `values()`. + +```{r functions} +# Variables — use the package helper is_categorical() as a column predicate. +# Without "des-delayed", the resolver calls it via vapply(data, fn, logical(1)), +# so it must accept one column and return a single logical value — which is_categorical() does. +picks( + datasets(choices = "ADSL", selected = "ADSL"), + variables( + choices = is_categorical(), + selected = 1L, + multiple = TRUE + ) +) + +# Values — select only even ages from the AGE column. +# Functions passed to values() must carry the "des-delayed" class so the resolver +# calls them with the column vector rather than treating them as a column predicate. +even_vals <- function(x) sort(unique(x[x %% 2 == 0])) +class(even_vals) <- append(class(even_vals), "des-delayed") + +p_even_ages <- picks( + datasets(choices = "ADSL", selected = "ADSL"), + variables(choices = "AGE", selected = "AGE", multiple = FALSE), + values( + choices = even_vals, + selected = even_vals + ) +) + +p_even_ages +``` + +#### Use of multiple to select more than one columns at once Use `multiple = TRUE` when analysts should pass more than one variable into the next step (for example stratifiers or outcomes together). @@ -122,6 +274,22 @@ picks_multiple_variables <- list( ) ) ``` +See `?picks` for other arguments that affect how choices/selections are presented to users regardless of +using static, tidyselect or functions to define them. + +#### Choices and Selection Summary + +| | Static | `tidyselect` | Function | +|---|:---:|:---:|:---:| +| `datasets()` | yes | yes | yes | +| `variables()` | yes | yes | yes | +| `values()` | yes | **no** | yes | + +Use **static** choices when the set of options is fixed and known at app-development time. +Use **`tidyselect`** when you want the choices to adapt to the shape of the data without writing +a custom function. Use **functions** when the logic is more involved, or when you need runtime +behavior for `values()`. + ## Trying these patterns inside teal From fd1fc492428f41a91e4ab65e501ad3bab5c47119 Mon Sep 17 00:00:00 2001 From: Oriol Senan <35930244+osenan@users.noreply.github.com> Date: Tue, 5 May 2026 18:57:03 +0200 Subject: [PATCH 05/12] Update vignettes/teal-picks-in-teal.Rmd MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: André Veríssimo <211358+averissimo@users.noreply.github.com> --- vignettes/teal-picks-in-teal.Rmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vignettes/teal-picks-in-teal.Rmd b/vignettes/teal-picks-in-teal.Rmd index 059dad4..a6634f2 100644 --- a/vignettes/teal-picks-in-teal.Rmd +++ b/vignettes/teal-picks-in-teal.Rmd @@ -101,7 +101,7 @@ Each `picks()` element has `choices` and `selected`. You can define them in four | Approach | Works with | |---|---| -| Default behavior | `variables()`, `values()`, and `datasets()` (`selected` only) | +| Default behavior - no arguments needed for generic usage | `datasets()`, `variables()`, `values()` | Static — character vector, integer index, or numeric range | `datasets()`, `variables()`, `values()` | | `tidyselect` helpers — `everything()`, `starts_with()`, `where()`, … | `datasets()`, `variables()` only | | Function — an R function applied at runtime to the data | `datasets()`, `variables()`, `values()` | From 860776bbe755a38d101219e19c83b2741bd36048 Mon Sep 17 00:00:00 2001 From: Oriol Senan <35930244+osenan@users.noreply.github.com> Date: Tue, 5 May 2026 18:57:22 +0200 Subject: [PATCH 06/12] Update vignettes/teal-picks-in-teal.Rmd MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: André Veríssimo <211358+averissimo@users.noreply.github.com> --- vignettes/teal-picks-in-teal.Rmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vignettes/teal-picks-in-teal.Rmd b/vignettes/teal-picks-in-teal.Rmd index a6634f2..a50eaff 100644 --- a/vignettes/teal-picks-in-teal.Rmd +++ b/vignettes/teal-picks-in-teal.Rmd @@ -110,7 +110,7 @@ The sections below walk through each approach with runnable examples. #### Defaults Defaults depend on the slot type. -For `datasets()`, there is no default for `choices`; define at least one dataset unless `check_no_dataset = FALSE`. +For `datasets()`, the default `choices` are all available datasets. A `picks()` call needs a `datasets()` as first positional argument, except when `check_no_dataset = FALSE`. For `variables()`, the default `choices` is all variables in the selected dataset. For `values()`, the default `choices` is all values of the selected variable. For `selected`, the default is the first available choice, or all choices when `multiple = TRUE`. From f3b570d72fd481cc0d95bc2065c6b21d530522de Mon Sep 17 00:00:00 2001 From: Oriol Senan <35930244+osenan@users.noreply.github.com> Date: Tue, 5 May 2026 18:57:51 +0200 Subject: [PATCH 07/12] Update vignettes/teal-picks-in-teal.Rmd MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: André Veríssimo <211358+averissimo@users.noreply.github.com> --- vignettes/teal-picks-in-teal.Rmd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vignettes/teal-picks-in-teal.Rmd b/vignettes/teal-picks-in-teal.Rmd index a50eaff..2f6d450 100644 --- a/vignettes/teal-picks-in-teal.Rmd +++ b/vignettes/teal-picks-in-teal.Rmd @@ -130,8 +130,8 @@ picks( #### Static choices -Pass a character vector to `choices` to enumerate options exactly. Use `selected` to set the -default. Integer indices work too (for example `selected = 1L` means the first element of +Pass a character vector to `choices` to enumerate options exactly. Use `selected` to set the default. +Integer indices work too (for example `selected = 1L` means the first element of `choices`). ```{r static} From 6d723cc7bc05058a71ebbced22162cae0aa085f4 Mon Sep 17 00:00:00 2001 From: Oriol Senan <35930244+osenan@users.noreply.github.com> Date: Tue, 5 May 2026 18:58:25 +0200 Subject: [PATCH 08/12] Update vignettes/teal-picks-in-teal.Rmd MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: André Veríssimo <211358+averissimo@users.noreply.github.com> --- vignettes/teal-picks-in-teal.Rmd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vignettes/teal-picks-in-teal.Rmd b/vignettes/teal-picks-in-teal.Rmd index 2f6d450..1d03ff6 100644 --- a/vignettes/teal-picks-in-teal.Rmd +++ b/vignettes/teal-picks-in-teal.Rmd @@ -170,8 +170,8 @@ p_values #### `tidyselect` helpers -`tidyselect` predicates let `choices` and `selected` adapt to the actual data at runtime instead -of being hard-coded. This is supported for `datasets()` and `variables()`. +`tidyselect` predicates let `choices` and `selected` adapt to the actual data at runtime instead of being hard-coded. +This is supported for `datasets()` and `variables()`. Commonly used helpers: From 418750a4f0e966a9c4beead7d0190686d9e79ab7 Mon Sep 17 00:00:00 2001 From: Oriol Senan <35930244+osenan@users.noreply.github.com> Date: Tue, 5 May 2026 18:58:44 +0200 Subject: [PATCH 09/12] Update vignettes/teal-picks-in-teal.Rmd MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: André Veríssimo <211358+averissimo@users.noreply.github.com> --- vignettes/teal-picks-in-teal.Rmd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vignettes/teal-picks-in-teal.Rmd b/vignettes/teal-picks-in-teal.Rmd index 1d03ff6..d46017c 100644 --- a/vignettes/teal-picks-in-teal.Rmd +++ b/vignettes/teal-picks-in-teal.Rmd @@ -223,8 +223,8 @@ p_a_prefix You can pass a plain R function as `choices` or `selected`. The function receives the relevant context object (the current dataset for `datasets()` and `variables()`, the current column vector -for `values()`) and must return the subset to use. This is the only runtime-dynamic approach -supported by `values()`. +for `values()`) and must return the subset to use. +This is the only runtime-dynamic approach supported by `values()`. ```{r functions} # Variables — use the package helper is_categorical() as a column predicate. From 271a880ad2695bbf9158fa2782891bf9a406c1fa Mon Sep 17 00:00:00 2001 From: Oriol Senan <35930244+osenan@users.noreply.github.com> Date: Tue, 5 May 2026 18:59:05 +0200 Subject: [PATCH 10/12] Update vignettes/teal-picks-in-teal.Rmd MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: André Veríssimo <211358+averissimo@users.noreply.github.com> --- vignettes/teal-picks-in-teal.Rmd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vignettes/teal-picks-in-teal.Rmd b/vignettes/teal-picks-in-teal.Rmd index d46017c..dacdd5d 100644 --- a/vignettes/teal-picks-in-teal.Rmd +++ b/vignettes/teal-picks-in-teal.Rmd @@ -182,8 +182,8 @@ Commonly used helpers: - `tidyselect::all_of()` / `tidyselect::any_of()` — vector-based selection (error-safe or silent) - Integer indices such as `1L`, `1L:3L` — select by position -> Note: `tidyselect` is not supported by `values()`. Use explicit vectors or a function -> there instead (see [Functions](#functions)). +> Note: `tidyselect` is not supported by `values()`. +> Use explicit vectors or a function there instead (see [Functions](#functions)). ```{r tidyselect} # Datasets — offer any data.frame in the teal_data object From 80bfd5e71d909c683d27630ef21646d485af707c Mon Sep 17 00:00:00 2001 From: osenan Date: Tue, 5 May 2026 19:09:31 +0200 Subject: [PATCH 11/12] docs: fix vignette defaults --- vignettes/teal-picks-in-teal.Rmd | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/vignettes/teal-picks-in-teal.Rmd b/vignettes/teal-picks-in-teal.Rmd index dacdd5d..84e581c 100644 --- a/vignettes/teal-picks-in-teal.Rmd +++ b/vignettes/teal-picks-in-teal.Rmd @@ -110,10 +110,11 @@ The sections below walk through each approach with runnable examples. #### Defaults Defaults depend on the slot type. -For `datasets()`, the default `choices` are all available datasets. A `picks()` call needs a `datasets()` as first positional argument, except when `check_no_dataset = FALSE`. -For `variables()`, the default `choices` is all variables in the selected dataset. -For `values()`, the default `choices` is all values of the selected variable. -For `selected`, the default is the first available choice, or all choices when `multiple = TRUE`. + +* For `datasets()`, the default `choices` are all available datasets. A `picks()` call needs a `datasets()` as first positional argument, except when `check_no_dataset = FALSE`. +* For `variables()`, the default `choices` is all variables in the selected dataset. +* For `values()`, the default `choices` is all values of the selected variable. +* For `selected`, the default is the first available choice, or all choices when `multiple = TRUE`. ```{r defaults} picks( From 7dba2116bb3dae3678810a332c56ea9b04289dc3 Mon Sep 17 00:00:00 2001 From: osenan Date: Wed, 6 May 2026 16:58:07 +0200 Subject: [PATCH 12/12] chore: add vignettes into page --- _pkgdown.yaml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/_pkgdown.yaml b/_pkgdown.yaml index e6425ac..013e599 100644 --- a/_pkgdown.yaml +++ b/_pkgdown.yaml @@ -5,9 +5,15 @@ template: navbar: structure: - left: [intro, reference, news] + left: [intro, reference, articles, news] right: [search, github] +articles: + - title: Vignettes + contents: + - teal-picks-in-teal + - teal-picks-standalone-shiny + reference: - title: Picks desc: Define hierarchical data selections