How to use selectInput with an editable DT table

Hi all,

I have some code written for a little app i'm looking to make some improvements to.

I want the user to be able to use the selectInput dropdown to select which period names are selected and the function applied to. The user can then change the total duration column and it'll multiply the rest of the columns (except m.min, acc.TD, acc.HSR and acc.Speed) by total duration. Ultimately, i'd love a 2nd table under the existing one that is a summary of all columns (sum of each).

I've attached a sample dataset and my existing code below. Any help would be greatly appreciated!


# Load required libraries

library(shiny)
library(shinydashboard)
library(tidyverse)
library(knitr)
library(ggimage)
library(DT)
library(kableExtra)
library(shinythemes)
library(reactablefmtr)

# Data Preparation ----

database <- read_csv("Dataset.csv") %>% na.omit() %>% filter(`Player Availability` == "Main Training") # Import unclean dataset 

database$`Time Spend Between 85-95% Max HR` <- as.numeric(database$`Time Spend Between 85-95% Max HR`)/60
database$`Time Spend Above 95% Max HR` <- as.numeric(database$`Time Spend Above 95% Max HR`)/60
database$`Total Duration` <- as.numeric(database$`Total Duration`)/60

database <- database %>% select(`Period Name`, `Total Distance`,`Total Duration`,`Meterage Per Minute`, `Distance 19-23kmph`, `Distance 23-25kmph`, `Distance 25-45kmph`, Accel, Decel, `Time Spend Above 95% Max HR`, `Time Spend Between 85-95% Max HR`)


database <- database %>% group_by(`Period Name`) %>% summarise(across(where(is.numeric), ~ mean(.x, na.rm = TRUE)))

database <- database %>% mutate(`Total Distance` = `Total Distance`/`Total Duration`,
                                M.Min  = `Meterage Per Minute`,
                                `HSR > 19kmph` = (`Distance 19-23kmph` + `Distance 23-25kmph` + `Distance 25-45kmph`)/`Total Duration`,
                                `Total 25+kmph` = (`Distance 25-45kmph`/ `Total Duration`),
                                Accel = Accel/`Total Duration`,
                                Decel = Decel/`Total Duration`,
                                Time.Above.85 = (`Time Spend Above 95% Max HR` + `Time Spend Between 85-95% Max HR`)/`Total Duration`)

database <- database %>% mutate(`Total Duration` = 1)

database1 <- database %>% select(`Period Name`,`Total Duration`,`Total Distance`, `M.Min`, `HSR > 19kmph`, `Total 25+kmph`, Accel, Decel,Time.Above.85) 
# Select only relevant information 

database1 <- database1 %>% mutate_at(3:6, round,0) %>% mutate_at(7:9, round,2) %>% mutate(Acc.TD = cumsum(`Total Distance`),
                                                                                          Acc.HSR = cumsum(`HSR > 19kmph`),
                                                                                          Acc.Speed = cumsum(`Total 25+kmph`))


database1 <- database1 %>% select(`Period Name`, `Total Duration`, M.Min, `Total Distance`, Acc.TD, `HSR > 19kmph`, Acc.HSR, `Total 25+kmph`, Acc.Speed, Accel, Decel, Time.Above.85)


### Module
modFunction <- function(input, output, session, data, reset) {
  
  v <- reactiveValues(data = data)
  
  proxy = dataTableProxy("mod_table")
  
  observeEvent(input$mod_table_cell_edit, {
    info = input$mod_table_cell_edit
    i = info$row
    j = info$col
    k = info$value
    
    isolate(
      if (j %in% match("Total Duration", names(v$data))) {
        # Filter numeric columns (excluding "Total Duration") for multiplication
        numeric_cols <- names(v$data)[sapply(v$data, is.numeric) & names(v$data) != "Total Duration"]
        
        # Multiply each numeric column in the current row by the new Total Duration value
        for (col in numeric_cols) {
          v$data[i, col] <- v$data[i, col] * k
        }
        # Update the edited Total Duration cell
        v$data[i, j] <- k
      }
    )
    
    # Update the cumulative sum column when a cell is edited
    if (j == which(names(v$data) == "Total Distance")) {
      v$data$Cumulative_Distance[i] <- cumsum(v$data$`Total Distance`[1:i])
    }
    
    replaceData(proxy, v$data, resetPaging = FALSE)
  })
  ### Reset Table
  observeEvent(reset(), {
    v$data <- data
  })
  
  output$mod_table <- DT::renderDataTable({
    
    datatable(v$data, editable = list(target = 'cell', disable = list(cols = which(!names(v$data) %in% "Total Duration"))))
  })
  
  return(v)
}

modFunctionUI <- function(id) {
  ns <- NS(id)
  DT::dataTableOutput((ns("mod_table")))
  
}

shinyApp(
  dashboardPage(
    dashboardHeader(title = "Drill Wizard"),
    dashboardSidebar(
      width = 200, # Adjust sidebar width here
      selectInput("selected_rows", "Select Drills:", choices = database1$`Period Name`, multiple = TRUE)),
    dashboardBody(
      modFunctionUI("editable"),
      div(DTOutput("table_output"), style = "margin-bottom: 100px; margin-top: 20px;text-align: center;"),
      div(DTOutput("summary_table_output"), style = "margin-top: 20px;text-align: center;"),
    ),
    # Set the shinytheme to "cosmo"
    shinytheme("cosmo")
  ),
  server = function(input, output) {
    
    
    demodata<-database1
    edited <- callModule(modFunction,"editable", demodata,
                         reset = reactive(input$reset))
    data_df_final <- reactiveValues()
    observe(
      {data_df_final$data <- edited$data}
    )
    observe(print(data_df_final$data))
    
    
  }
)

I have formatted your post for you.

see : FAQ: How to format your code

read_csv("Dataset.csv") will simply not work on anyones machine but yours...
You can review the general reprex guide and the shiny one, for tips on how to communicate your data over text

How do I share data for a reprex?

You might use tools such as the library datapasta, or the base function dput() to share a portion of data in code form, i.e. that can be copied from forum and pasted to R session.

Reprex Guide

shiny reprex guide

Shiny debugging and reprex guide

This topic was automatically closed 54 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.