@@ -97,7 +97,7 @@ get_column_def <- function(name, field, value) {
9797 )
9898}
9999
100- dataview_table <- function (data , start = 0 , end = NULL , sortModel = NULL ) {
100+ dataview_table <- function (data , start = 0 , end = NULL , sortModel = NULL , filterModel = NULL ) {
101101
102102 if (is.matrix(data )) {
103103 data <- as.data.frame.matrix(data )
@@ -109,8 +109,8 @@ dataview_table <- function(data, start = 0, end = NULL, sortModel = NULL) {
109109 data <- data.table :: copy(data )
110110 data.table :: setDT(data )
111111
112- data [, " (row)" : = .I ]
113- setcolorder(data , neworder = " (row)" , before = 1 )
112+ data [, `:=`( " (row)" = numeric (), rowId = .I ) ]
113+ data.table :: setcolorder(data , neworder = c( " (row)" , " rowId " ) , before = 1 )
114114
115115 # number of rows & original column names
116116 .nrow <- nrow(data )
@@ -121,20 +121,69 @@ dataview_table <- function(data, start = 0, end = NULL, sortModel = NULL) {
121121 .colnames <- trimws(.colnames )
122122 }
123123
124- # capture or generate rownames
125- if (.row_names_info(data ) > 0L ) {
126- rownames_ <- rownames(data )
127- rownames(data ) <- NULL
128- } else {
129- rownames_ <- seq_len(.nrow )
130- }
131-
132124 fields <- sprintf(" x%d" , seq_along(.colnames ))
133-
134- # map x1→"(row)", x2→first real col, …
135125 field_map <- setNames(.colnames , fields )
136126
137- # ── SORT data before slicing ──
127+ if (! is.null(filterModel ) && length(filterModel ) > 0 ) {
128+
129+ filter_strings <- lapply(names(filterModel ), function (fld ) {
130+ fd <- filterModel [[fld ]]
131+ col_name <- field_map [[fld ]]
132+
133+ if (! is.null(fd $ type ) && ! is.null(fd $ filter )) {
134+ op <- fd $ type
135+ raw <- fd $ filter
136+
137+ # quote or coerce the filter literal
138+ lit <- if (inherits(data [[col_name ]], " Date" )) {
139+ sprintf(' as.Date("%s")' , raw )
140+ } else if (is.numeric(data [[col_name ]])) {
141+ as.numeric(raw )
142+ } else {
143+ sprintf(' "%s"' , gsub(' "' , ' \\\\ "' , raw ))
144+ }
145+
146+ # build the right comparison or string test
147+ expr <- switch (op ,
148+ equals = sprintf(' get("%s") == %s' , col_name , lit ),
149+ notEqual = sprintf(' get("%s") != %s' , col_name , lit ),
150+ greaterThan = sprintf(' get("%s") > %s' , col_name , lit ),
151+ greaterThanOrEqual = sprintf(' get("%s") >= %s' , col_name , lit ),
152+ lessThan = sprintf(' get("%s") < %s' , col_name , lit ),
153+ lessThanOrEqual = sprintf(' get("%s") <= %s' , col_name , lit ),
154+ contains = sprintf(' grepl(%s, get("%s"), fixed=TRUE)' , lit , col_name ),
155+ notContains = sprintf(' !grepl(%s, get("%s"), fixed=TRUE)' , lit , col_name ),
156+ startsWith = sprintf(' startsWith(get("%s"), %s)' , col_name , lit ),
157+ endsWith = sprintf(' endsWith(get("%s"), %s)' , col_name , lit ),
158+ regexp = sprintf(' grepl(%s, get("%s"))' , lit , col_name ),
159+ blank = sprintf(' is.na(get("%s")) | get("%s") == ""' , col_name , col_name ),
160+ notBlank = sprintf(' !is.na(get("%s")) & get("%s") != ""' , col_name , col_name ),
161+ inRange = {
162+ hi <- if (inherits(data [[col_name ]], " Date" )) {
163+ sprintf(' as.Date("%s")' , fd $ filterTo )
164+ } else {
165+ as.numeric(fd $ filterTo )
166+ }
167+ sprintf(' get("%s") >= %s & get("%s") <= %s' ,
168+ col_name , lit , col_name , hi )
169+ },
170+ NULL
171+ )
172+ return (expr )
173+ }
174+ NULL
175+ })
176+
177+ filter_strings <- Filter(Negate(is.null ), filter_strings )
178+ # combine with &&
179+ if (length(filter_strings ) > 0 ) {
180+ combined <- paste(filter_strings , collapse = " & " )
181+ data <- data [eval(parse(text = combined ))]
182+ }
183+ }
184+
185+ nFiltered <- nrow(data )
186+
138187 if (! is.null(sortModel ) && length(sortModel ) > 0 ) {
139188
140189 cols <- vapply(sortModel , function (s ) field_map [[s $ colId ]], FUN.VALUE = " " )
@@ -143,21 +192,19 @@ dataview_table <- function(data, start = 0, end = NULL, sortModel = NULL) {
143192 data.table :: setorderv(data , cols , order = ords )
144193 }
145194
146- if (is.null(end )) end <- .nrow
195+ if (is.null(end )) end <- nFiltered
147196 s <- as.integer(start ) + 1
148- e <- min(.nrow , as.integer(end ))
197+ e <- min(nFiltered , as.integer(end ))
149198
150- if (s > .nrow || e < 1 || s > e ) {
151- rows <- data [0 , , drop = FALSE ]
152- rownums <- integer(0 )
199+ if (s > nFiltered || e < 1 || s > e ) {
200+ rows <- data [0 ]
153201 } else {
154- rows <- data [s : e , , drop = FALSE ]
155- rownums <- rownames_ [s : e ]
202+ rows <- data [s : e ][, " (row)" : = s : e ]
156203 }
157204
158205 names(rows ) <- fields
159206 class(rows ) <- " data.frame"
160- attr(rows , " row.names" ) <- .set_row_names(length( rownums ))
207+ attr(rows , " row.names" ) <- .set_row_names(nrow( rows ))
161208
162209 rows <- jsonlite :: fromJSON(
163210 jsonlite :: toJSON(rows , dataframe = " rows" , na = " null" , auto_unbox = TRUE )
@@ -171,7 +218,8 @@ dataview_table <- function(data, start = 0, end = NULL, sortModel = NULL) {
171218 list (
172219 columns = columns ,
173220 rows = rows ,
174- totalRows = .nrow
221+ totalRows = nFiltered ,
222+ totalUnfiltered = .nrow
175223 )
176224}
177225
@@ -229,9 +277,9 @@ if (use_webserver) {
229277 return (result )
230278 }
231279 },
232- dataview_fetch_rows = function (varname , start , end , sortModel , ... ) {
280+ dataview_fetch_rows = function (varname , start , end , sortModel , filterModel , ... ) {
233281 obj <- get(varname , envir = .GlobalEnv )
234- out <- dataview_table(obj , start , end , sortModel )
282+ out <- dataview_table(obj , start , end , sortModel , filterModel )
235283 out $ columns <- NULL
236284 return (out )
237285 }
0 commit comments