Skip to content

Commit 548b664

Browse files
authored
Merge pull request #30 from cynkra/f-15-filter
Add search bar
2 parents bdbafb6 + c2ee62c commit 548b664

File tree

8 files changed

+130
-8
lines changed

8 files changed

+130
-8
lines changed

DESCRIPTION

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ Suggests:
2929
shiny,
3030
quarto,
3131
knitr,
32-
dplyr
32+
dplyr,
33+
palmerpenguins
3334
Config/testthat/edition: 3
3435
VignetteBuilder: quarto

R/cheetah.R

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
#' @param height Height of the widget
1010
#' @param elementId The element ID for the widget
1111
#' @param rownames Logical. Whether to show rownames. Defaults to TRUE.
12+
#' @param search Whether to enable a search field on top of the table.
13+
#' Default to `disabled`. Use `exact` for exact matching
14+
#' or `contains` to get larger matches.
1215
#'
1316
#' @return An HTML widget object of class 'cheetah' that can be:
1417
#' \itemize{
@@ -29,8 +32,10 @@ cheetah <- function(
2932
width = NULL,
3033
height = NULL,
3134
elementId = NULL,
32-
rownames = TRUE
35+
rownames = TRUE,
36+
search = c("disabled", "exact", "contains")
3337
) {
38+
search <- match.arg(search)
3439
# Only show rownames if they are character strings (meaningful) and rownames is TRUE
3540
processed_rn <- process_rownames(data, columns, rownames)
3641

@@ -47,7 +52,7 @@ cheetah <- function(
4752

4853
data_json <- toJSON(data, dataframe = "rows")
4954
# forward options using x
50-
x = list(data = data_json, columns = columns)
55+
x <- list(data = data_json, columns = columns, search = search)
5156

5257
# create widget
5358
htmlwidgets::createWidget(

inst/htmlwidgets/cheetah.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/cheetah.Rd

Lines changed: 6 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

srcjs/widgets/cheetah.js

Lines changed: 92 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,102 @@ HTMLWidgets.widget({
3838
const grid = new cheetahGrid.ListGrid({
3939
parentElement: document.getElementById(id),
4040
header: columns,
41-
// Array data to be displayed on the grid
42-
records: x.data,
4341
// Column fixed position
4442
// frozenColCount: 1,
4543
});
4644

45+
// Search feature
46+
if (x.search !== 'disabled') {
47+
const filterDataSource = new cheetahGrid
48+
.data
49+
.FilterDataSource(
50+
cheetahGrid.data.DataSource.ofArray(x.data)
51+
);
52+
grid.dataSource = filterDataSource;
53+
54+
$(`#${el.id}`).prepend(
55+
`<label>Filter:</label><input id="${el.id}-filter-input" style="margin: 10px;"/>`
56+
)
57+
58+
$(`#${el.id}-filter-input`).on('input', (e) => {
59+
const filterValue = $(e.currentTarget).val();
60+
filterDataSource.filter = filterValue
61+
? (record) => {
62+
// filtering method
63+
for (const k in record) {
64+
let testCond;
65+
switch (x.search) {
66+
case 'contains':
67+
testCond = `${record[k]}`.indexOf(filterValue) >= 0;;
68+
break;
69+
case 'exact':
70+
let r = new RegExp(`^${filterValue}$`);
71+
testCond = r.test(`${record[k]}`);
72+
break;
73+
default:
74+
console.log(`${x.search} value not implemented yet.`);
75+
}
76+
if (testCond) {
77+
return true;
78+
}
79+
}
80+
return false;
81+
}
82+
: null;
83+
grid.invalidate();
84+
})
85+
} else {
86+
// Array data to be displayed on the grid
87+
grid.records = x.data;
88+
}
89+
90+
91+
// Search feature
92+
if (x.search !== 'disabled') {
93+
const filterDataSource = new cheetahGrid
94+
.data
95+
.FilterDataSource(
96+
cheetahGrid.data.DataSource.ofArray(x.data)
97+
);
98+
grid.dataSource = filterDataSource;
99+
100+
$(`#${el.id}`).prepend(
101+
`<label>Filter:</label><input id="${el.id}-filter-input" style="margin: 10px;"/>`
102+
)
103+
104+
$(`#${el.id}-filter-input`).on('input', (e) => {
105+
const filterValue = $(e.currentTarget).val();
106+
filterDataSource.filter = filterValue
107+
? (record) => {
108+
// filtering method
109+
for (const k in record) {
110+
let testCond;
111+
switch (x.search) {
112+
case 'contains':
113+
testCond = `${record[k]}`.indexOf(filterValue) >= 0;;
114+
break;
115+
case 'exact':
116+
let r = new RegExp(`^${filterValue}$`);
117+
testCond = r.test(`${record[k]}`);
118+
break;
119+
default:
120+
console.log(`${x.search} value not implemented yet.`);
121+
}
122+
if (testCond) {
123+
return true;
124+
}
125+
}
126+
return false;
127+
}
128+
: null;
129+
grid.invalidate();
130+
})
131+
} else {
132+
// Array data to be displayed on the grid
133+
grid.records = x.data;
134+
}
135+
136+
47137
// Only is Shiny exists
48138
if (HTMLWidgets.shinyMode) {
49139
const {

tests/testthat/_snaps/cheetah.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# test cheetah
2+
3+
Code
4+
cheetah(iris, search = "plop")
5+
Condition
6+
Error in `match.arg()`:
7+
! 'arg' should be one of "disabled", "exact", "contains"
8+

tests/testthat/test-cheetah.R

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,8 @@ test_that("test cheetah", {
3030
shiny::testServer(server, {
3131
expect_s3_class(session$getOutput("grid"), "json")
3232
})
33+
34+
expect_snapshot(error = TRUE, {
35+
cheetah(iris, search = "plop")
36+
})
3337
})

vignettes/cheetahR.qmd

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ knitr::opts_chunk$set(
1616

1717
```{r setup}
1818
library(cheetahR)
19+
library(palmerpenguins)
1920
library(dplyr)
2021
```
2122

@@ -92,6 +93,14 @@ head(airquality, 10) %>%
9293
)
9394
```
9495

96+
## Filtering data
97+
98+
You can filter data by setting `search` to either `exact` or `contains` when you call `cheetah()` like so:
99+
100+
```{r}
101+
cheetah(penguins, search = "contains")
102+
```
103+
95104
## Sortable columns
96105

97106
To make a column sortable, you can pass `sort = TRUE` to the `column_def()` function:
@@ -112,7 +121,7 @@ cheetah(
112121

113122
If you want finer control over the sorting logic and provide your own, you can pass a `htmlwidgets::JS` callback instead:
114123

115-
```r
124+
```{r}
116125
cheetah(
117126
mtcars,
118127
columns = list(

0 commit comments

Comments
 (0)