I would like to make some rows expand on click, i.e. by clicking on the arrow. Is there a way in reactable
to add java script code to specific rows? There exists and option for expanding/collapsing all rows on click in reactable
(see here), but it does not do exactly what I need. Is there any reactable/javascript guru out there who has an idea how this might be feasible.
The required output is designed with kableExtra
but I think my problem is more suited for reactable
.
df_open <- tibble::tibble(
Category = c("Fruits ▼︎", "Apple", "Banana",
"Kiwi", "Vegetable ▼︎", "Carrots ▼︎", "Red Carrots", "Orange Carrots", "Diary"),
Value_sum = c(1:9),
Value_one = c(10:18),
Value_two = c(200:208)
)
df_closed <- tibble::tibble(
Category = c("Fruits ▶︎","Vegetable ▶︎", "Diary"),
Value_sum = c(1, 5,9),
Value_one = c(10,14,18),
Value_two = c(200, 204,208)
)
library(kableExtra)
# all collapsed, everything shown
kbl(df_open, escape = FALSE) |>
kable_styling(bootstrap_options = "bordered") |>
row_spec(row = c(2:4, 6), extra_css = "padding-left:30px;") |>
row_spec(row = c(7,8), extra_css = "padding-left:50px")
# all closed
kbl(df_closed, escape = FALSE) |>
kable_styling(bootstrap_options = "bordered")
Completely folded table:
Raw Data:
df <- tibble::tibble(
Category = c("Fruits", "Apple", "Banana", "Kiwi", "Vegetable", "Carrots", "Red Carrots", "Orange Carrots", "Diary"),
Value_sum = c(1:9),
Value_one = c(10:18),
Value_two = c(200:208),
Another_column = "ABC"
)
My attempt using this blog post
library(dplyr)
library(reactable)
top_level <- df |>
mutate(id = c(1,1,1,1,2,2, 2,2,3),
id_large = c(1, NA, NA, NA,2, NA, NA, NA, 3)) |>
filter(!is.na(id_large)) |>
relocate(id, .before = 1) |>
select(-id_large)
second_level <- df |>
mutate(id = c(1,1,1,1,2,2, 2,2,3),
id_large = c(1, NA, NA, NA,2, NA, NA, NA, 3)) |>
filter(is.na(id_large)) |>
relocate(id, .before = 1) |>
select(-id_large)
reactable(
data = top_level,
compact = TRUE,
striped = TRUE,
resizable = TRUE,
columns = list(
id = colDef(name = "ID", show = FALSE)),
details = function(index) { # index is the row number of current row.
sec_lvl = second_level[second_level$id == top_level$id[index], ]
reactable(data = sec_lvl,
compact = TRUE,
bordered = TRUE,
resizable = TRUE,
colna
columns = list(
id = colDef(name = "ID", show = FALSE))
)
}
)
I'm not sure this is currently possible with {reactable} - but it looks like an open feature request: https://github.com/glin/reactable/issues/147
The {DT} package might be able to do something like this. Using the code in this blog post: https://laustep.github.io/stlahblog/posts/DT_childTables.html you can create something similar. In the example below, the NestedData
function and callback
are copied directly from the blog post.
The idea is to store your data as a nested list. Ideally, you'd have some column in your df
data frame that identifies what level the table is and use that to subset it, rather than manually creating the different data frames as I've done here.
main <- tibble::tribble(
~Category, ~Value_sum, ~Value_one, ~Value_two, ~Another_column,
"Fruits", 1, 10, 200, "ABC",
"Vegetable", 5, 14, 204, "ABC",
"Dairy", 9, 18, 208, "ABC",
)
fruits <- tibble::tribble(
~Category, ~Value_sum, ~Value_one, ~Value_two, ~Another_column,
"Apple", 2, 11, 200, "ABC",
"Banana", 3, 12, 201, "ABC",
"Kiwi", 4, 13, 202, "ABC",
)
veg <- tibble::tribble(
~Category, ~Value_sum, ~Value_one, ~Value_two, ~Another_column,
"Carrots", 6, 15, 205, "ABC"
)
carrots <- tibble::tribble(
~Category, ~Value_sum, ~Value_one, ~Value_two, ~Another_column,
"Red Carrots", 2, 11, 200, "ABC",
"Oraneg Carrots", 3, 12, 201, "ABC"
)
Dat <- NestedData(
dat = main,
children = list(
fruits,
list(
veg,
children = list(
carrots
)
),
data.frame(NULL)
)
)
library(DT)
datatable(
Dat,
callback = callback, rownames = rowNames, escape = -colIdx-1,
options = list(
paging = FALSE,
searching = FALSE,
columnDefs = list(
list(
visible = FALSE,
targets = ncol(Dat)-1+colIdx
),
list(
orderable = FALSE,
className = "details-control",
targets = colIdx
),
list(
className = "dt-center",
targets = "_all"
)
)
)
)
gives something like this: