Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bugfix: Correctly sort re-ordered columns #1096

Merged
merged 9 commits into from
Nov 16, 2023
4 changes: 4 additions & 0 deletions R/datatables.R
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,10 @@ datatable = function(
if (is.null(options[['autoWidth']])) options$autoWidth = FALSE
# disable CSS classes for ordered columns
if (is.null(options[['orderClasses']])) options$orderClasses = FALSE
# enable column names for column reordering by default
if (is.null(options[['columns']])) {
options$columns = lapply(names(data), function(e) list(name = e))
}

cn = base::colnames(data)
if (missing(colnames)) {
Expand Down
3 changes: 3 additions & 0 deletions R/shiny.R
Original file line number Diff line number Diff line change
Expand Up @@ -663,6 +663,9 @@ dataTablesFilter = function(data, params) {
for (ord in q$order) {
k = ord[['column']] # which column to sort
d = ord[['dir']] # direction asc/desc
# If colReorder is enabled, need to find column name rather than index
l = q$columns[[k]][['name']]
if (l %in% names(data)) k = as.character(match(l, names(data)) - 1)
if (q$columns[[k]][['orderable']] != 'true') next
col = data[, as.integer(k) + 1]
oList[[length(oList) + 1]] = (if (d == 'asc') identity else `-`)(
Expand Down
78 changes: 78 additions & 0 deletions tests/testit/test-sort.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
library(testit)

# Factors and strings are searched differently.
# Older versions of R don't have this set.
op = options(stringsAsFactors = FALSE)

# Helpers to create client queries that run without errors
clientQuery = function(data, columns = lapply(names(data), columnQuery)) {
columns = rep_len(columns, ncol(data))
names(columns) = seq_len(ncol(data)) - 1
list(
draw = '0',
start = '0',
length = '10',
escape = 'true',
search = list(
value = '',
regex = 'false',
caseInsensitive = 'true',
smart = 'true'
),
columns = columns,
order = list()
)
}

columnQuery = function(name = '', orderable = TRUE) {
list(
name = name,
orderable = tolower(orderable),
searchable = 'true',
search = list(value = '', regex = 'false')
)
}

orderQuery = function(column, dir = 'asc') {
list(
column = column,
dir = dir
)
}

assert('server-side sort handler works', {
tbl = data.frame(
foo = c('foo', 'bar', 'baz'),
bar = c('bar', 'baz', 'foo')
)

query = clientQuery(tbl)
out = dataTablesFilter(tbl, query)
(identical(out$data, unname(tbl)))

query = clientQuery(tbl)
query$order[[1]] = orderQuery('0', 'asc')
tbl_sort = tbl[order(tbl$foo), ]
out = dataTablesFilter(tbl, query)
(identical(out$data, unname(tbl_sort)))

query = clientQuery(tbl)
query$order[[1]] = orderQuery('1', 'desc')
tbl_sort = tbl[order(tbl$bar, decreasing = TRUE), ]
out = dataTablesFilter(tbl, query)
(identical(out$data, unname(tbl_sort)))
})

assert('server-side sort handler works with re-ordered columns', {
tbl = data.frame(
foo = c('foo', 'bar', 'baz'),
bar = c('bar', 'baz', 'foo')
)

query = clientQuery(tbl, lapply(c("bar", "foo"), columnQuery))
# order is indexed against re-ordered columns
query$order[[1]] = orderQuery('0', 'asc')
tbl_sort = tbl[order(tbl$bar), ]
out = dataTablesFilter(tbl, query)
(identical(out$data, unname(tbl_sort)))
})