Saturday, February 21, 2026

Shiny: Highlighting DT Rows

I am working on a Shiny application involving data tables (displayed using the DT library). There is one particular table in which I would like my code to highlight rows meeting certain criteria, which the application will evaluate. Not knowing how to set a background color for an entire row in a table, I went down a rabbit hole with Shiny Assistant, the relatively knew AI bot trained to help with Shiny coding. It took way too many attempts, but eventually I stumbled on prompts that got me more or less what I need.

It turns out there are some tricky bits, so I put together a small demonstration application. The demo app displays a portion of the mtcars dataset (which installs with R) and lets the user select, via check boxes, which rows to highlight. You can download the source code here. I will just mention a few things about the code.

  • The check boxes to select which rows are highlighted belong to a single checkboxGroupInput control named "selected". Initially I used observeEvent() to watch for changes to input$selected, which almost worked. The problem was that when the user removed the last check mark, signalling that no rows should be highlighted, the observer did not see an event and the table continued to have one highlighted row. Switching to observe()fixed the part about not seeing an event. I have no explanation as to why. See the next paragraph for the rest of the fix.
  • Early on, the table itself would not display until there was at least one row selected for highlighting. After switching to observe(), removing the last checkmark still failed to clear all formatting. I was forced to use an if-else approach (the highlightRows() function), in which the code applies the row formatting only if at least one row is selected. I am still in the dark as to why this is necessary.
  • The formatting code ends up being translated to JavaScript to communicate with the DataTables library. DataTables uses zero-based indexing, which explains why the specification of which columns to highlight (in this case, all of them) is 0:(ncol(df) - 1) rather than 1:ncol(df).
  • Using reactiveVal() may be overkill in the demo application, since input$selected is itself reactive (I think) (maybe). I used it in part because I intend to use it in the larger application I am building, and I wanted to be sure it worked.