remove the same rows in two rhandsontables in a shiny app

Hi, I have a shinyapp, in which there are two tables that are generated with rhandsontable package. table_1 (hot) is totally independent of table_2 (hot2), but in table_2 there are some columns that are calculated from user inputs (in table_2) and the values from table_1 (like column F in the below example). In table_1, user should be able to insert or remove rows (one row or multiple rows). How can I remove the same rows in table_2, that the user has just removed in table_1?

As an example, In this code:

library(shiny)
library(rhandsontable)
library(dplyr)

ui <- fluidPage(
  h3("table_1"),
  rHandsontableOutput("hot"),
  br(),
  h3("table_2"),
  rHandsontableOutput("hot2")
)

server <- function(input, output, session) {
  dat <- data.frame(A = c(1:5), B = c(5:1))
  dat2 <- data.frame(C = c(4:8), D = c(10:14), E = c(6:10))
  dat2 <- mutate(dat2, F = dat2$D + dat$A)
  
  output$hot <- renderRHandsontable(rhandsontable(dat))
  output$hot2 <- renderRHandsontable(rhandsontable(dat2))
  
  observeEvent({
    input$hot
    input$hot2
    }, {
    dat <- hot_to_r(input$hot)
    dat2 <- hot_to_r(input$hot2)
    dat2 <- mutate(dat2, F = dat2$D + dat$A)
    
    output$hot <- renderRHandsontable(rhandsontable(dat) %>% 
                                        hot_context_menu(allowColEdit = F))
    output$hot2 <- renderRHandsontable(rhandsontable(dat2) %>%
                                         hot_context_menu(allowRowEdit = F, allowColEdit = F) %>%
                                         hot_col(col = "F", readOnly = T))
  })
}

shinyApp(ui, server)

If I select rows 2 and 4 of table_1 and remove them, how can the same rows in table_2 get removed? Is it possible to find out which rows are removed?

Hi @moji. I suggest a way to check with is.na to identify the deleted row and remove the row content.

library(shiny)
library(rhandsontable)
library(dplyr)

ui <- fluidPage(
 h3("table_1"),
 rHandsontableOutput("hot"),
 br(),
 h3("table_2"),
 rHandsontableOutput("hot2")
)

server <- function(input, output, session) {
 dat <- data.frame(A = c(1:5), B = c(5:1))
 dat2 <- data.frame(C = c(4:8), D = c(10:14), E = c(6:10))
 dat2 <- mutate(dat2, F = dat2$D + dat$A)
 
 output$hot <- renderRHandsontable(rhandsontable(dat))
 output$hot2 <- renderRHandsontable(rhandsontable(dat2))
 
 observeEvent({
   input$hot
   input$hot2
 }, {
   dat <- hot_to_r(input$hot)
   dat2 <- hot_to_r(input$hot2)
   dat2 <- mutate(dat2, F = dat2$D + dat$A)
   
   naPos <- which(is.na(dat2$F))
   if(length(naPos) != 0) {
     dat2[naPos,] <- NA_integer_
   }
   
   output$hot <- renderRHandsontable(rhandsontable(dat) %>% 
                                       hot_context_menu(allowColEdit = F))
   output$hot2 <- renderRHandsontable(rhandsontable(dat2) %>%
                                        hot_context_menu(allowRowEdit = F, allowColEdit = F) %>%
                                        hot_col(col = "F", readOnly = T))
 })
}

shinyApp(ui, server)

Thank you @raytong for the reply, but it doesn't solve the problem. Actually, by removing rows in table_1, dat$A will become a vector shorter than dat2$D, but it doesn't result in NA in dat2$F. R will handle it the way it deals with adding two vectors with different elements. You can test it and see that the corresponding rows in table_2, are not deleted in the app.

@moji. Sorry for misunderstand your question. rhandsontable have a feature that including the recently change event and argument in the input value. So, you can check if the row are removed from the table hot. If yes, use the row index in int and ct to remove the rows in table hot2.

library(shiny)
library(rhandsontable)
library(dplyr)

ui <- fluidPage(
    h3("table_1"),
    rHandsontableOutput("hot"),
    br(),
    h3("table_2"),
    rHandsontableOutput("hot2"),
    textOutput("selRow")
)

server <- function(input, output, session) {
    dat <- data.frame(A = c(1:5), B = c(5:1))
    dat2 <- data.frame(C = c(4:8), D = c(10:14), E = c(6:10))
    dat2 <- mutate(dat2, F = dat2$D + dat$A)

    output$hot <- renderRHandsontable(rhandsontable(dat))
    output$hot2 <- renderRHandsontable(rhandsontable(dat2))

    observeEvent({
        input$hot
    }, {
        dat <- hot_to_r(input$hot)
        dat2 <- hot_to_r(input$hot2)
        if (input$hot$changes$event == "afterRemoveRow") {
            delRows <- (input$hot$changes$ind + 1) : ((input$hot$changes$ind + 1) + (input$hot$changes$ct - 1))
            dat2 <- dat2[-delRows,]
        }
        dat2 <- mutate(dat2, F = dat2$D + dat$A)

        output$hot <- renderRHandsontable(rhandsontable(dat) %>%
                                              hot_context_menu(allowColEdit = F))
        output$hot2 <- renderRHandsontable(rhandsontable(dat2) %>%
                                               hot_context_menu(allowRowEdit = F, allowColEdit = F) %>%
                                               hot_col(col = "F", readOnly = T))
    })
}

shinyApp(ui, server)

It was a great solution if it would be possible to prevent users from multi-row selection. If I select only one row and remove it, it works fine; but if I select two rows (for example 2 and 4) and remove them, what happens is that only one row (and surprisingly in this example: row 3 !!!) will be removed. I don't know if it is a bug of the package or not, but what is important is that such behaviors make the app unstable and error-prone.

@moji. rhandsontable package did not report rows of non-consecutive remove, so can't help.

1 Like