I have a Shiny App with a DataTable that allows the user to see the margin made on various products while allowing edits on the buying and selling prices to recalculate said margin. To make obvious that those columns can be edited, I would like the editable cells and columns to appear like inputs from the start instead of having to doublecklick on them.
Here is what I would like to have displayed at launch :
And what I currently work with :
Below is a reproducible exemple :
# Libraries
library(shiny)
library(bslib)
library(tidyverse)
library(DT)
# JS code for Keyboard shortcuts
# Allow to use arrow-keys and Enter to edit and confirm new values in cells
js <- c(
"table.on('key', function(e, datatable, key, cell, originalEvent){",
" var targetName = originalEvent.target.localName;",
" if(key == 13 && targetName == 'body'){",
" $(cell.node()).trigger('dblclick.dt');",
" }",
"});",
"table.on('keydown', function(e){",
" var keys = [9,13,37,38,39,40];",
" if(e.target.localName == 'input' && keys.indexOf(e.keyCode) > -1){",
" $(e.target).trigger('blur');",
" }",
"});",
"table.on('key-focus', function(e, datatable, cell, originalEvent){",
" var targetName = originalEvent.target.localName;",
" var type = originalEvent.type;",
" if(type == 'keydown' && targetName == 'input'){",
" if([9,37,38,39,40].indexOf(originalEvent.keyCode) > -1){",
" $(cell.node()).trigger('dblclick.dt');",
" }",
" }",
"});"
)
modServ_EdiTable <- function(id, data_initialisation) {
moduleServer(id, function(input, output, session) {
# initialise the reactive data object for the table
data <- reactiveVal()
observe(data(data_initialisation()))
# render the table
output$dummyDT <- renderDT({
datatable(
data(),
selection = 'none',
editable = list(target = 'cell', disable = list(columns = c(0:1, 4))),
callback = JS(js),
extensions = 'KeyTable',
options = list(keys = TRUE)
)
})
# update the underlying data
observeEvent(input$dummyDT_cell_edit, {
data(
editData(data(), input$dummyDT_cell_edit) %>%
mutate(Margin = round(`Selling Price` - `Buying Price`, 2))
)
})
# return the data as a reactive
return(data)
})
}
server <- function(input, output, session) {
dummyData <- reactive({
tibble(
Material = c("Lead", "Tin", "Iron", "Copper", "Mercury", "Silver", "Gold"),
`Buying Price` = c(12.2, 10.3, 8, 5.6, 7.5, 22.9, 50),
`Selling Price` = c(18, 15, 12, 10, 11, 40, 100),
Margin = round(`Selling Price`, 2)
)
})
modServ_EdiTable("dummyId", data_initialisation = dummyData)
session$onSessionEnded(function() {stopApp()})
}
modUI_EdiTable <- function(id) {
ns <- NS(id)
card(DTOutput(ns("dummyDT")))
}
ui <- page_navbar(
nav_panel(title = "dummyPanel", modUI_EdiTable(id = "dummyId"))
)
shinyApp(ui, server)