Action button working only 1 time with {daff} html output in R {shiny}

Viewed 66

The code below is built in two parts for editing excel file in {shiny} with the excellent {dataEditr} package

  • First action is to write in new excel and click button to save
  • Second part, a modal dialog is shown for validating changes

But when I validate or not the changes, I can no more open the modal dialog when save button is clicked.

Plus, when I show only text or table in the modal dialog, all work fine.

library(shinydashboard)
library(daff)
library(dplyr)
library(DataEditR)

df1 = iris %>% slice(1:10) %>% select(-Species)
df2 = iris %>% slice(1:12)

# Define UI
ui = shinyUI(
  fluidPage(
    fluidRow(
      box(
        title = "First data",
        status = "success",
        width = 6,
        solidHeader = TRUE,
        collapsible = TRUE,
        dataEditUI(id = "old_data")
      ),
      box(
        title = "New data",
        status = "primary",
        width = 6,
        solidHeader = TRUE,
        collapsible = TRUE,
        dataEditUI(id = "new_data"),
        br(),
        actionButton("save", "Save!")
      )
    )
  )
)

# Define server
server = shinyServer(function(input, output, session) {
  
  data_old = dataEditServer(
    "old_data",
    data = df1, 
    col_readonly = names(df1),
    col_names = FALSE,
    col_options = TRUE,
    row_edit = FALSE
  )
  
  data_new = dataEditServer(
    "new_data",
    data = df2, 
    col_names = FALSE,
    col_options = TRUE,
    row_edit = FALSE
  ) 
  
  diff_data = reactive({
    daff::render_diff(
      daff::diff_data(
        data_old(),
        data_new()
      ), view = FALSE
    )
  })
  
  output$compare_df = renderUI({
    HTML(
      diff_data()
    )
  })
  
  observeEvent(
    input$save, {
      showModal(
        modalDialog(
          span(
            "Check modification before validation!",
            style = "color: red; font-size: 130%;"
          ),
          br(),
          br(),
          uiOutput("compare_df"),
          footer = tagList(
            modalButton("Cancel"),
            actionButton("ok", "OK")
          ),
          easyClose = TRUE,
          size = "l"
        )
      )
    }
  )
  
  observeEvent(
    input$ok, {
      print(data_new())
      removeModal()
    }
  )
  
})

shinyApp(ui, server)
1 Answers

daff::render_diff by default renders a complete HTML document. This causes JS errors when the modal is first displayed (i.e. the first time "Save!" is clicked). You can see this by changing the renderUI. The modal will show the literal HTML code instead of trying to render it

  output$compare_df = renderUI({
    div(# HTML(
      diff_data()
    )
  })

The fix is to use the fragment argument which will produce only the HTML table, which renderUI will know how to handle

  diff_data = reactive({
    daff::render_diff(
      daff::diff_data(
        data_old(),
        data_new()
      ), 
      view = FALSE,
      fragment = TRUE
    )
  })

The downside of this is the complete HTML document contains CSS in it that is not included with just the fragment. You are then responsible for styling the resulting table.

Related