I am currently working on a Shiny app where I want to have an input to select parts of an Rhandsontable. My goal is to do the validation and the cleaning of the cell range within the Shiny app and then pass the cleaned cell range to JavaScript to make the selection.
Here is the code I have so far (building on this post):
library(shiny)
library(htmlwidgets)
library(rhandsontable)
js <- "
function(el, x) {
let hot = this.hot;
Shiny.addCustomMessageHandler('handler_cell_range', function(message) {
console.log(message);
hot.selectCells([message]);
});
}
"
ui <- fluidPage(
textInput('cell_range', label = 'Cell range (start_row, start_col, end_col, end_row)',
value = '1,2,3,4', width = '500px'),
actionButton('bttn_cell_range', label = '', icon = icon('search')),
rHandsontableOutput('table_raw')
)
server <- function(input, output, session) {
# Render table
output$table_raw <- renderRHandsontable({
rhandsontable(iris) %>% onRender(js)
})
# Select range
observeEvent(input$bttn_cell_range, {
# Here there will be a lot of validation and cleaning of the cell range
# before it can be passed to js
# Clean cell range
cr <- input$cell_range
cr <- gsub(' ', '', cr) # Remove white space
cr <- strsplit(cr, ',')[[1]] # Split by ,
cr <- as.numeric(cr) - 1
# Send to javascript to make the selection on the rhandsontable
session$sendCustomMessage('handler_cell_range', message = cr)
})
}
shinyApp(ui = ui, server = server)
I am wondering if this is the correct way to proceed.
Your code makes sense. Below I show how to use the shinyvalidate package for this problem. This allows to have a message (Invalid cell range
) near the text input when the given cell range is not valid.
I'm using a regex (^\\d+,\\d+,\\d+,\\d+$
) to test whether the cell range has form number,number,number,number
after white spaces removal. It seems to work but I'm not a regex master.
library(shiny)
library(shinyvalidate)
ui <- fluidPage(
br(),
textInput("cell_range", "Enter cell range"),
actionButton('bttn_cell_range', label = '', icon = icon('search'))
)
server <- function(input, output, session) {
iv <- InputValidator$new()
iv$add_rule(
"cell_range",
rule = function(cellRange) {
test <- grepl("^\\d+,\\d+,\\d+,\\d+$", gsub(" ", "", cellRange))
if(test) {
return(NULL)
} else {
return("Invalid cell range")
}
}
)
iv$enable()
observeEvent(input$bttn_cell_range, {
req(iv$is_valid())
# Clean cell range
cr <- input$cell_range
cr <- gsub(' ', '', cr) # Remove white space
cr <- strsplit(cr, ',')[[1]] # Split by ,
cr <- as.numeric(cr) - 1
# Send to javascript to make the selection on the rhandsontable
session$sendCustomMessage('handler_cell_range', message = cr)
})
}
shinyApp(ui, server)