Data Entry Using Inputs & Edit with DT in R Shiny - I cannot get the edit part working

Viewed 174

The first part of the APP works with entering new Data points and this saves to an rds as needed, also updates the data table as expected. I want to be able to edit the DT as well and have this update the rds and main reactiveVal but not sure of the error message and now stuck.

Sample code below:

The Observe event is failing to update and can't work out why.

library(shiny)
library(shinythemes)
library(shinydashboard)
library(DT)

# Define UI 
ui <- fluidPage(theme = shinytheme("sandstone"),
                
                # header
                headerPanel("My Shiny Data entry app"),
                
                sidebarLayout(
                  # sidebar for form
                  sidebarPanel(
                    
                    tabBox(
                      tabPanel("Enter New",
                               
                               h3("Information",""),
                               textInput("name", "Patient Name",""),
                               textInput("age", "Patient Age",""),
                               textInput("id", "Patient ID",""),
                               radioButtons("gender", "Patient gender",
                                            c("None selected" = "",
                                              "male",
                                              "female" ,
                                              "other" ,
                                              "do no want to say")),
                               actionButton("update", "Next patient") 
                      ),
                      tabPanel("Edit", " ")
                    )
                  ),
                  
                  # output for viewing
                  mainPanel(
                    DT::dataTableOutput("x1"),
                  )   
                )
)

server <- function(input, output, session)  {
  
  # [ NEW ]
  ## Initilializing DataSet 
    # saveRDS(data.frame(Animal_ID = character(), 
    #                   Scan_ID = character(), 
    #                   Tech_ID = character(), 
    #                   Age_weeks = character(), 
    #                   stringsAsFactors = FALSE),  "data_entry_form.rds")

  # reactiveVal
  aniRoi2 <- reactiveVal(readRDS("data_entry_form.rds"))
  
  # Update 
  observeEvent(input$update,{
    to_add <- data.frame(
      Animal_ID = input$name, 
      Scan_ID = input$age, 
      Tech_ID = input$id, 
      Age_weeks = input$gender
    )
    
    newAniRoi2 <- rbind(aniRoi2(),to_add) # adding new data
    saveRDS(newAniRoi2, "data_entry_form.rds") # save rds 
    aniRoi2(newAniRoi2) # updating data
    
    # Cleaning Inputs
    updateTextInput(session,"name", "Patient Name","")
    updateTextInput(session,"age", "Patient Age","")
    updateTextInput(session,"id", "Patient ID","")
    updateRadioButtons(session,"gender", "Patient gender",
                       c("None selected" = "",
                         "male",
                         "female" ,
                         "other" ,
                         "do no want to say"))
  })
  
  # [ EDIT DT (Issue !) ]
  output$x1 = renderDT(aniRoi2(), selection = 'none', editable = TRUE)
  
  observeEvent(input$x1_cell_edit, { 
    aniRoi2()[input$x1_cell_edit$row,input$x1_cell_edit$col] <<- input$x1_cell_edit$value # ISSUE IS HERE ! [ This part is failing ]
    saveRDS(aniRoi2(), "data_entry_form.rds") # save rds
    aniRoi2(aniRoi2()) # updating data
  })              
}
shinyApp(ui, server)
1 Answers

Avoid to use a reactive dataset in datatable. Each time it changes, the table is re-rendered. It is better to use a proxy.

library(shiny)
library(shinythemes)
library(shinydashboard)
library(DT)

# Define UI 
ui <- fluidPage(
  theme = shinytheme("sandstone"),
  
  # header
  headerPanel("My Shiny Data entry app"),
  
  sidebarLayout(
    # sidebar for form
    sidebarPanel(
      
      tabBox(
        tabPanel("Enter New",
                 
                 h3("Information",""),
                 textInput("name", "Patient Name",""),
                 textInput("age", "Patient Age",""),
                 textInput("id", "Patient ID",""),
                 radioButtons("gender", "Patient gender",
                              c("None selected" = "",
                                "male",
                                "female" ,
                                "other" ,
                                "do no want to say")),
                 actionButton("update", "Next patient") 
        ),
        tabPanel("Edit", " ")
      )
    ),
    
    # output for viewing
    mainPanel(
      DTOutput("x1"),
    )   
  )
)

dat0 <- data.frame(
  Animal_ID = character(), 
  Scan_ID   = character(),
  Tech_ID   = character(),
  Age_weeks = character(),
  stringsAsFactors = FALSE
)

server <- function(input, output, session)  {
  
  # [ NEW ]
  ## Initilializing DataSet 
  # saveRDS(data.frame(Animal_ID = character(), 
  #                   Scan_ID = character(), 
  #                   Tech_ID = character(), 
  #                   Age_weeks = character(), 
  #                   stringsAsFactors = FALSE),  "data_entry_form.rds")
  
  # reactiveVal
  aniRoi2 <- reactiveVal(dat0)

  output[["x1"]] <- renderDT({
    datatable(
      dat0, 
      selection = "none", 
      editable = TRUE
    )
  })
  
  proxy <- dataTableProxy("x1")
  
  # Update 
  observeEvent(input[["update"]], {
    
    to_add <- data.frame(
      Animal_ID = input[["name"]], 
      Scan_ID   = input[["age"]], 
      Tech_ID   = input[["id"]], 
      Age_weeks = input[["gender"]],
      stringsAsFactors = FALSE
    )
    
    newAniRoi2 <- rbind(aniRoi2(), to_add) # adding new data
    
    replaceData(proxy, newAniRoi2, resetPaging = FALSE)
    
    saveRDS(newAniRoi2, "data_entry_form.rds") # save rds 
    aniRoi2(newAniRoi2) # updating data
    
    # Cleaning Inputs
    updateTextInput(session, "name", "Patient Name", "")
    updateTextInput(session, "age", "Patient Age", "")
    updateTextInput(session, "id", "Patient ID", "")
    updateRadioButtons(session, "gender", "Patient gender",
                       c("None selected" = "",
                         "male",
                         "female" ,
                         "other" ,
                         "do no want to say"))
  })

  observeEvent(input[["x1_cell_edit"]], { 
    info <- input[["x1_cell_edit"]]
    newAniroi2 <- 
      editData(aniRoi2(), info, proxy, rownames = TRUE, resetPaging = FALSE)
    aniRoi2(newAniroi2)
    saveRDS(newAniroi2, "data_entry_form.rds") # save rds
  })
  
}

shinyApp(ui, server)
Related