glin / reactable

Interactive data tables for R
https://glin.github.io/reactable
Other
613 stars 79 forks source link

table "breaks" when searching for non existing string #176

Open Laurent-Smeets-GSS-Account opened 3 years ago

Laurent-Smeets-GSS-Account commented 3 years ago

I made a small alteration to an example on the reactable website, which seems to break the code some home. If I add searchable = T to a table with a custom rowstyle and then search for "X" the table disappears instead of giving me the expected "No rows found" text. Is there anything I can change to the JS code to not have this problem.

library(dplyr)

data <- as_tibble(MASS::painters, rownames = "Painter") %>%
  filter(School %in% c("A", "B", "C")) %>%
  mutate(School = recode(School, A = "Renaissance", B = "Mannerist", C = "Seicento")) %>%
  select(Painter, School, everything()) %>%
  group_by(School) %>%
  slice(1:3)

reactable(
  data,
  searchable = T,
  defaultSorted = list(School = "asc", Drawing = "desc"),
  borderless = TRUE,
  rowStyle = JS("
    function(rowInfo, state) {
      // Add horizontal separators between groups when sorting by school
      var firstSorted = state.sorted[0]
      if (firstSorted && firstSorted.id === 'School') {
        var nextRow = state.pageRows[rowInfo.viewIndex + 1]
        if (nextRow && rowInfo.row['School'] !== nextRow['School']) {
          // Use box-shadow to add a 2px border without taking extra space
          return { boxShadow: 'inset 0 -2px 0 rgba(0, 0, 0, 0.1)' }
        }
      }
    }
  ")
)
glin commented 2 years ago

This happens when there's no data to show, and there's just a single padding row in the table. Padding rows don't receive a rowInfo object, so the rowStyle function fails with a JavaScript error:

TypeError: Cannot read property 'viewIndex' of undefined

To work around this, you can have the rowStyle function ignore padding rows like this:

library(dplyr)

data <- as_tibble(MASS::painters, rownames = "Painter") %>%
  filter(School %in% c("A", "B", "C")) %>%
  mutate(School = recode(School, A = "Renaissance", B = "Mannerist", C = "Seicento")) %>%
  select(Painter, School, everything()) %>%
  group_by(School) %>%
  slice(1:3)

reactable(
  data,
  searchable = T,
  defaultSorted = list(School = "asc", Drawing = "desc"),
  borderless = TRUE,
  rowStyle = JS("
    function(rowInfo, state) {
      // Ignore padding rows
      if (!rowInfo) return

      // Add horizontal separators between groups when sorting by school
      var firstSorted = state.sorted[0]
      if (firstSorted && firstSorted.id === 'School') {
        var nextRow = state.pageRows[rowInfo.viewIndex + 1]
        if (nextRow && rowInfo.row['School'] !== nextRow['School']) {
          // Use box-shadow to add a 2px border without taking extra space
          return { boxShadow: 'inset 0 -2px 0 rgba(0, 0, 0, 0.1)' }
        }
      }
    }
  ")
)

I'll update the cookbook example to prevent confusion for future users. But I also think this could be addressed/fixed in reactable - it doesn't make total sense to apply custom row styles to padding rows, so maybe padding rows should be ignored. Thanks for reporting this.