1

I have an rhandsontable and I want the WHOLE ROW to be yellow if the cell in the text in the last column ("Comments") includes string "missed".

The code below highlights any cell that has a value 'missed', but not the whole row. Besides, I'd like the row to turn yellow when a cell in the last column CONTAINS "missed" - even inside a longer string, and not just when it contains only "missed" - as it is written now - I just don't know how to match strings in JavaScript.

DF = data.frame(a = 1:2, b = 3:4, Comments = c("missed etc", "missed"))
rhandsontable(DF, width = 550, height = 300) %>%
  hot_cols(renderer = " function (instance, td, row, col, prop, value, cellProperties) { 
                     Handsontable.renderers.TextRenderer.apply(this, arguments); 
                     if(value == 'missed') { 
                     td.style.background = 'yellow' } 
                     }")

Thank you very much!

To clarify, in reality, I am dealing with a larger table that I am rendering in rShiny. So, ideally the solution that works for the little data frame above should also work here. Currently it is not (nothing shows up at all):

    output$session_table <- renderRHandsontable({
        req(input$select_a_patient)
        patient_nr <- which(patient_names_reactive$names %in% input$select_a_patient)

        row_highlight = which(grepl("missed", 
sessions_reactive$sessions[[patient_nr]]$Comments))-1

        rhandsontable(sessions_reactive$sessions[[patient_nr]],
                      row_highlight = row_highlight,
                      width = 1000, height = 500) %>% 
            hot_rows(fixedRowsTop = 1) %>%
            hot_table(highlightCol = TRUE, highlightRow = TRUE) %>% 
            hot_validate_numeric(cols = c(3, 5), min = 0, max = 500) %>% 
            hot_col(c(1, 3, 5, 6, 8), valign = 'htCenter') %>%
            hot_cols(renderer = " 
            function (instance, td, row, col, prop, value, cellProperties) { 
                     Handsontable.renderers.TextRenderer.apply(this, arguments); 

                     tbl = this.HTMLWidgets.widgets[0]
                     hrows = tbl.params.row_highlight
                     hrows = hrows instanceof Array ? hrows : [hrows]

                     if (hrows.includes(row)) { 
                       td.style.background = 'yellow' } 
                     }") %>% hot_col(c(5, 8), renderer = " 
                        function (instance, td, row, col, prop, value, cellProperties) {
                           Handsontable.renderers.TextRenderer.apply(this, arguments);
                           td.style.fontWeight = 'bold';
                           td.style.color = '#fc0f03';}"
            )
user3245256
  • 1,842
  • 4
  • 24
  • 51

1 Answers1

1

Based on the tutorial using a custom renderer:

https://jrowen.github.io/rhandsontable/

you could do the following (doing the string match outside of the js).

DF = data.frame(a = 1:4, b = 3:6, Comments = c("missed etc", "", "missed", ""))

rhandsontable(DF, row_highlight = which(grepl("missed", DF$Comments))-1, width = 550, height = 300) %>%
  hot_cols(renderer = "function (instance, td, row, col, prop, value, cellProperties) { 
                     Handsontable.renderers.TextRenderer.apply(this, arguments); 

                     tbl = this.HTMLWidgets.widgets[0]

                     hrows = tbl.params.row_highlight
                     hrows = hrows instanceof Array ? hrows : [hrows]

                     if (hrows.includes(row)) { 
                       td.style.background = 'yellow' } 
                     }")

Edit: This apparently requires additional modification if used as a shiny app. As noted in documentation:

When using this approach in a shiny app or in a document with more than one widget, the widget search logic will need to be more robust.

If instance.params is available, we can try the following:

library(shiny)
library(rhandsontable)

DF = data.frame(a=1:10, b=3:12, c=c("Dog", "Cat", "Mouse", 5:11), d=3:12, e=1:10, f=1:10, g=1:10, h=2:11, Comments = c("missed etc", rep("", 7), "missed", ""))

ui <- fluidPage(
  mainPanel(
    rHandsontableOutput('table')
  )
)

server = function(input, output, session) {

  output$table <- renderRHandsontable({
    row_highlight = which(grepl("missed", DF$Comments))-1
    col_highlight = c(5,8)-1
    rhandsontable(DF, row_highlight = row_highlight, col_highlight = col_highlight, width = 550, height = 300) %>%
      hot_rows(fixedRowsTop = 1) %>%
      hot_table(highlightCol = TRUE, highlightRow = TRUE) %>% 
      hot_validate_numeric(cols = c(3, 5), min = 0, max = 500) %>% 
      hot_col(c(1, 3, 5, 6, 8), valign = 'htCenter') %>%
      hot_cols(renderer = "
            function (instance, td, row, col, prop, value, cellProperties) {
                     Handsontable.renderers.TextRenderer.apply(this, arguments);

                     if (instance.params) {
                       hrows = instance.params.row_highlight
                       hrows = hrows instanceof Array ? hrows : [hrows]
                       hcols = instance.params.col_highlight
                       hcols = hcols instanceof Array ? hcols : [hcols]

                       if (hrows.includes(row)) {
                         td.style.background = 'yellow' 
                       }

                       if (hcols.includes(col)) {
                         td.style.fontWeight = 'bold'
                         td.style.color = '#fc0f03'
                       }
                     }
            }"
      ) 
  })
}

shinyApp(ui, server)

Edit1: Integrated second renderer with the first one, so that column formatting doesn't overwrite row background color.

Edit2: Adding explanation regarding col_highlight added.

Starting at the beginning we have col_highlight = c(5,8)-1 which creates a vector storing the columns we wish to have different formatting (bold, red font). We subtract one since arrays in javascript are zero-based.

The following line for rhandsontable allows us to pass in col_highlight = col_highlight so that we can later access these selected columns through instance.params.col_highlight in the renderer function later on. Once we access them and assign them to hcols, we make sure it is an array if it wasn't already.

The statement if (hcols.includes(col)) checks to see if the hcols array contains the column (col) being rendered. If the column rendered is 5, this is contained in the vector (5, 8), and the td.style would be set to bold and red.

Note that since hrows would only change background color, and hcols would only change font bold and color, one does not overwrite the other, and can be used together.

table with select yellow background row and red and bold columns

Ben
  • 28,684
  • 5
  • 23
  • 45
  • Actually, that's really great and answers the question the way I asked it. However, In real life I have some other code that defines different aspects of my table, e.g., "hot_col(c(1, 3, 5, 6, 8), valign = 'htCenter')". Thus, I need to 'continue' my pipe with a "%>%". And I don't know how to do it with your line 'row_highlight <- ...' - because that line is outside of the pipeline... :( Is there any way to achieve the same thing - but inside the rhandsontable function? – user3245256 Sep 28 '19 at 15:41
  • Thanks a lot, Ben, really appreciate it. Your solution is ingenious - and it totally works with the little data frame. But it's not working in my larger/longer code. I posted it (along with your solution) at the bottom of my post. Any idea why it's rendering nothing? (clarification: sessions_reactive$sessions[[patient_nr]] is a reactive value - and it is the data frame I am rendering). Can it be that nothing is being shown because currently I don't have 'missed' in the column 'Comments' anywhere? – user3245256 Sep 28 '19 at 18:35
  • No, adding row_highlight = row_highlight inside rhandstontable didn't help – user3245256 Sep 28 '19 at 19:15
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/200098/discussion-between-ben-and-user3245256). – Ben Sep 28 '19 at 19:16
  • It's funny - it works perfectly when DT is a standalone table. Again: in my real tables I don't currently have a single comment (in column Comments) with 'missed'. Can this be the reason? – user3245256 Sep 28 '19 at 19:29
  • Ben, I want to thank you very much for all the time you took to solve it. Who would have known it'll end up such a difficult question and that the solution that works in simple rhandsontable is not working inside Shiny. Really appreciate it! PS: notice that the last two elements of the pipe (hot_cols you've written and hot_col after it) overwrite each other (in this case - red font cancels yellow background). That's not a big deal for me, but it would be cool to have them both work on the same cells. It's probably very complicated! :-) – user3245256 Sep 29 '19 at 18:25
  • The whole row highlighting works, but those red columns are not red anymore :) I guess that formatting works in sequence and the last step overwrites the first step. – user3245256 Sep 29 '19 at 18:50
  • You don't get the same result as in my picture? Columns 5 and 8 appear red and bold font? Also did you copy/paste the entire code? It also needs `col_highlight` as well... – Ben Sep 29 '19 at 18:51
  • It's working - I missed the parameters (col_highlight on top)! THANK YOU! – user3245256 Sep 29 '19 at 19:17
  • I just realized - I don't understand what the last statement means: if (hcols.includes(col)). I mean, it's working, but I just wanted columns 5 and 8 to be bold and red. I am not sure what hcols.includes(col) means here... – user3245256 Oct 03 '19 at 03:40
  • I added an additional explanation under `Edit2` in the answer above. Hope this is helpful. – Ben Oct 03 '19 at 13:38