Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Suggests:
shiny,
quarto,
knitr,
dplyr
dplyr,
palmerpenguins
Config/testthat/edition: 3
VignetteBuilder: quarto
9 changes: 7 additions & 2 deletions R/cheetah.R
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
#' @param height Height of the widget
#' @param elementId The element ID for the widget
#' @param rownames Logical. Whether to show rownames. Defaults to TRUE.
#' @param search Whether to enable a search field on top of the table.
#' Default to `disabled`. Use `exact` for exact matching
#' or `contains` to get larger matches.
#'
#' @return An HTML widget object of class 'cheetah' that can be:
#' \itemize{
Expand All @@ -29,8 +32,10 @@ cheetah <- function(
width = NULL,
height = NULL,
elementId = NULL,
rownames = TRUE
rownames = TRUE,
search = c("disabled", "exact", "contains")
) {
search <- match.arg(search)
# Only show rownames if they are character strings (meaningful) and rownames is TRUE
processed_rn <- process_rownames(data, columns, rownames)

Expand All @@ -47,7 +52,7 @@ cheetah <- function(

data_json <- toJSON(data, dataframe = "rows")
# forward options using x
x = list(data = data_json, columns = columns)
x <- list(data = data_json, columns = columns, search = search)

# create widget
htmlwidgets::createWidget(
Expand Down
2 changes: 1 addition & 1 deletion inst/htmlwidgets/cheetah.js

Large diffs are not rendered by default.

7 changes: 6 additions & 1 deletion man/cheetah.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

94 changes: 92 additions & 2 deletions srcjs/widgets/cheetah.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,102 @@ HTMLWidgets.widget({
const grid = new cheetahGrid.ListGrid({
parentElement: document.getElementById(id),
header: columns,
// Array data to be displayed on the grid
records: x.data,
// Column fixed position
// frozenColCount: 1,
});

// Search feature
if (x.search !== 'disabled') {
const filterDataSource = new cheetahGrid
.data
.FilterDataSource(
cheetahGrid.data.DataSource.ofArray(x.data)
);
grid.dataSource = filterDataSource;

$(`#${el.id}`).prepend(
`<label>Filter:</label><input id="${el.id}-filter-input" style="margin: 10px;"/>`
)

$(`#${el.id}-filter-input`).on('input', (e) => {
const filterValue = $(e.currentTarget).val();
filterDataSource.filter = filterValue
? (record) => {
// filtering method
for (const k in record) {
let testCond;
switch (x.search) {
case 'contains':
testCond = `${record[k]}`.indexOf(filterValue) >= 0;;
break;
case 'exact':
let r = new RegExp(`^${filterValue}$`);
testCond = r.test(`${record[k]}`);
break;
default:
console.log(`${x.search} value not implemented yet.`);
}
if (testCond) {
return true;
}
}
return false;
}
: null;
grid.invalidate();
})
} else {
// Array data to be displayed on the grid
grid.records = x.data;
}


// Search feature
if (x.search !== 'disabled') {
const filterDataSource = new cheetahGrid
.data
.FilterDataSource(
cheetahGrid.data.DataSource.ofArray(x.data)
);
grid.dataSource = filterDataSource;

$(`#${el.id}`).prepend(
`<label>Filter:</label><input id="${el.id}-filter-input" style="margin: 10px;"/>`
)

$(`#${el.id}-filter-input`).on('input', (e) => {
const filterValue = $(e.currentTarget).val();
filterDataSource.filter = filterValue
? (record) => {
// filtering method
for (const k in record) {
let testCond;
switch (x.search) {
case 'contains':
testCond = `${record[k]}`.indexOf(filterValue) >= 0;;
break;
case 'exact':
let r = new RegExp(`^${filterValue}$`);
testCond = r.test(`${record[k]}`);
break;
default:
console.log(`${x.search} value not implemented yet.`);
}
if (testCond) {
return true;
}
}
return false;
}
: null;
grid.invalidate();
})
} else {
// Array data to be displayed on the grid
grid.records = x.data;
}


// Only is Shiny exists
if (HTMLWidgets.shinyMode) {
const {
Expand Down
8 changes: 8 additions & 0 deletions tests/testthat/_snaps/cheetah.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# test cheetah

Code
cheetah(iris, search = "plop")
Condition
Error in `match.arg()`:
! 'arg' should be one of "disabled", "exact", "contains"

4 changes: 4 additions & 0 deletions tests/testthat/test-cheetah.R
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,8 @@ test_that("test cheetah", {
shiny::testServer(server, {
expect_s3_class(session$getOutput("grid"), "json")
})

expect_snapshot(error = TRUE, {
cheetah(iris, search = "plop")
})
})
11 changes: 10 additions & 1 deletion vignettes/cheetahR.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ knitr::opts_chunk$set(

```{r setup}
library(cheetahR)
library(palmerpenguins)
library(dplyr)
```

Expand Down Expand Up @@ -92,6 +93,14 @@ head(airquality, 10) %>%
)
```

## Filtering data

You can filter data by setting `search` to either `exact` or `contains` when you call `cheetah()` like so:

```{r}
cheetah(penguins, search = "contains")
```

## Sortable columns

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

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

```r
```{r}
cheetah(
mtcars,
columns = list(
Expand Down