Compare commits

...

9 Commits

Author SHA1 Message Date
Alan Dipert
5f2d1a0b26 No recursion 2019-08-21 14:00:11 +00:00
Alan Dipert
b16e3f16c7 Thouroughly overhaul and comment choicesWithNames() 2019-08-16 23:06:40 +00:00
Alan Dipert
c1dd4d1e51 Split listify into series of passes 2019-08-14 23:05:00 +00:00
Alan Dipert
832ee531b8 Expand comment 2019-08-06 03:36:20 +00:00
Alan Dipert
462214c7a8 Add test for 013-selectize regression 2019-08-06 03:36:10 +00:00
Alan Dipert
89ea280c94 Expand comment, don't import stats 2019-08-06 03:31:47 +00:00
Alan Dipert
f2d852d006 Add .github to .Rbuildignore 2019-08-06 03:04:21 +00:00
Winston Chang
f3cc8c69bf Re-document 2019-08-06 03:04:21 +00:00
Alan Dipert
5fce090e44 selectInput/selectizeInput: Fix handling of character(1) choices 2019-08-06 03:00:10 +00:00
6 changed files with 60 additions and 33 deletions

View File

@@ -20,3 +20,4 @@
^revdep$
^TODO-promises.md$
^manualtests$
^\.github$

View File

@@ -90,41 +90,58 @@ generateOptions <- function(inputId, selected, inline, type = 'checkbox',
div(class = "shiny-options-group", options)
}
# Take a vector or list, and convert to named list. Also, if any children are
# vectors with length > 1, convert those to list. If the list is unnamed,
# convert it to a named list with blank names.
listify <- function(x) {
if (is.list(x) || is.null(x)) {
asNamedVector(lapply(x, listify))
} else if (is.character(x)) {
if (length(x) == 1 && is.null(names(x))) {
x
# True when a choice list item represents a group of related inputs
isGroup <- function(choice) {
length(choice) > 1 || !is.null(names(choice))
}
# True when choices is a list and contains at least one group of related inputs
hasGroups <- function(choices) {
is.list(choices) && Position(isGroup, choices, nomatch = 0)
}
# Assigns empty names to x if it's unnamed, and then fills any empty names with
# the corresponding value coerced to a character(1)
setDefaultNames <- function(x) {
x <- asNamed(x)
emptyNames <- names(x) == ""
names(x)[emptyNames] <- as.character(x)[emptyNames]
x
}
# Makes a character vector out of x in a way that preserves names if x is a
# factor.
asCharacter <- function(x) {
stats::setNames(as.character(x), names(x))
}
processFlatChoices <- function(choices) {
choices <- setDefaultNames(asCharacter(choices))
as.list(choices)
}
processGroupedChoices <- function(choices) {
choices <- asNamed(choices)
choices <- mapply(function(name, group, choice) {
if (group && name == "") {
stop('All sub-lists in "choices" must be named.')
} else if (group) {
processFlatChoices(choice)
} else {
as.list(asNamedVector(x))
as.character(choice)
}
} else {
# Can get here if x is a factor.
listify(stats::setNames(as.character(x), names(x)))
}
}, names(choices), lapply(choices, isGroup), choices, SIMPLIFY = FALSE)
setDefaultNames(choices)
}
# Takes a vector or list, and adds names (same as the value) to any entries
# without names. Coerces all leaf nodes to `character`.
choicesWithNames <- function(choices) {
choices <- listify(choices)
if (length(choices) == 0) return(choices)
# Recurse into any subgroups
choices <- mapply(choices, names(choices), FUN = function(choice, name) {
if (!is.list(choice)) return(choice)
if (name == "") stop('All sub-lists in "choices" must be named.')
choicesWithNames(choice)
}, SIMPLIFY = FALSE)
# default missing names to choice values
missing <- names(choices) == ""
names(choices)[missing] <- as.character(choices)[missing]
choices
if (length(choices) == 0) {
choices
} else if (hasGroups(choices)) {
processGroupedChoices(choices)
} else {
processFlatChoices(choices)
}
}

View File

@@ -639,7 +639,7 @@ ShinySession <- R6Class(
# that the resulting object is represented as an object in JSON
# instead of an array, and so that the RDS data structure is of a
# consistent type.
values <- lapply(values, asNamedVector)
values <- lapply(values, asNamed)
if (length(values) == 0) {
return(httpResponse(400, "text/plain",

View File

@@ -173,8 +173,8 @@ anyUnnamed <- function(x) {
}
# Given a vector/list, returns a named vector (the labels will be blank).
asNamedVector <- function(x) {
# Given a vector/list, returns a named vector/list (the labels will be blank).
asNamed <- function(x) {
if (is.null(names(x))) {
names(x) <- character(length(x))
}

View File

@@ -15,6 +15,10 @@ showReactLog(time = TRUE)
reactlogReset()
}
\arguments{
\item{time}{A boolean that specifies whether or not to display the
time that each reactive takes to calculate a result.}
}
\description{
Provides an interactive browser-based tool for visualizing reactive
dependencies and execution in your application.

View File

@@ -69,6 +69,11 @@ test_that("Repeated names for selectInput and radioButtons choices", {
test_that("Choices are correctly assigned names", {
# Empty character vector
expect_identical(
choicesWithNames(c("")),
stats::setNames(list(""), "")
)
# Unnamed character vector
expect_identical(
choicesWithNames(c("a","b","3")),