Last active
June 20, 2019 19:59
-
-
Save geebioso/8d1c3a165a3968beddd95bf736db1b01 to your computer and use it in GitHub Desktop.
This code creates deletable dynamic accordions that load a modal when they are created. The modal is triggering too many times after an accordion is deleted and then reloaded.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
makeReactiveTrigger <- function() { | |
rv <- shiny::reactiveValues(a = 0) | |
list( | |
depend = function() { | |
rv$a | |
}, | |
trigger = function() { | |
rv$a <- shiny::isolate(rv$a + 1) | |
} | |
) | |
} | |
# Test Module --------------------------------------------------------------- | |
library(shiny) | |
library(glue) | |
load("~/git_repos/lrw-ms-shinyapps/shinyutility/testimage.rdata") | |
ui <- fluidPage( | |
tagList( | |
tags$div(id = "RowPlaceholder", class = 'box-group'), | |
actionButton('add', label = "Add accordions"), | |
actionButton('delete', label = "Delete accordions") | |
) | |
) | |
server <- function(input, output, session) { | |
auto_populate_btn = reactive(input$add) | |
do_delete_all = reactive(input$delete) | |
#!!! you can change the number of batteries if it helps debug | |
auto_stack_instructions = reactiveVal(c("Battery1", "Battery2")) | |
current_accordions <- reactiveVal() | |
auto_pop_modal <- modalDialog( | |
div(style = "text-align: center; font-size: 28px;", | |
h2("Auto Populating"), #, style = "text-align: center;"), | |
icon("spinner", class = "fa-spin")), | |
footer = NULL, size = 'm') | |
delete_trigger <- makeReactiveTrigger() | |
delete_all = reactive({ | |
do_delete_all() # actionButton | |
delete_trigger$depend() # trigger off the auto_populate_btn actionButton | |
}) | |
num <- reactiveVal(0) | |
insert_accordion <- function( | |
battery_name, | |
auto_populate_btn = auto_populate_btn, | |
delete = delete_all, | |
auto_pop_modal){ | |
current_accordions(c(current_accordions(), battery_name)) | |
accordion_item_div_id <- glue::glue("accordion_item_div_{battery_name}") | |
accordion_item_id <- glue::glue("accordion_item_{battery_name}") | |
delete_btn_id <- glue::glue("delete_{battery_name}") | |
accordion_item <- | |
tags$div(id = accordion_item_div_id, | |
shinydashboardPlus::accordionItem( | |
id = accordion_item_id, | |
title = battery_name, | |
color = "secondary", | |
collapsed = FALSE, | |
shiny::actionButton( | |
delete_btn_id, label = NULL, | |
icon = shiny::icon("trash-alt"), width = '40px') | |
) | |
) | |
insertUI( | |
selector = glue::glue("#{'RowPlaceholder'}"), | |
where = "beforeEnd", | |
ui = accordion_item, | |
immediate = TRUE | |
) | |
delete_module_trigger <- makeReactiveTrigger() | |
# !!! Dean - this observeEvent will eventually be inside a sub-module that is called | |
# for each accordion. The idea is to pass the modal through to a sub-module | |
# and have it display when we are peforming some computations there. I pulled | |
# it out of the sub-module because we still see the bug here | |
observeEvent(auto_populate_btn(), { | |
showModal(auto_pop_modal) | |
Sys.sleep(2) | |
removeModal() | |
}) | |
delete_accordion <- function(delete_btn_id){ | |
delete_accordion_num <- strsplit(delete_btn_id, "delete_")[[1]][2] | |
accordion_item_div_id <- glue::glue("accordion_item_div_{delete_accordion_num}") | |
delete_btn_id <- glue::glue("delete_{delete_accordion_num}") | |
removeUI(selector = glue::glue("#{accordion_item_div_id}"), immediate = TRUE) | |
shinyjs::runjs(glue::glue("Shiny.onInputChange(‘{accordion_item_div_id}’, null)")) | |
shinyjs::runjs(glue::glue("Shiny.onInputChange(‘{delete_btn_id}’, null)")) | |
current_accordions( | |
current_accordions()[-match(delete_accordion_num, current_accordions())] | |
) | |
} | |
observeEvent(auto_populate_btn(), delete_trigger$trigger(), | |
ignoreInit = TRUE, priority = 2) | |
observeEvent(input[[delete_btn_id]],{ | |
delete_accordion(delete_btn_id) | |
delete_module_trigger$trigger() | |
}, once = TRUE, ignoreInit = TRUE) | |
observeEvent(delete(),{ | |
delete_accordion(delete_btn_id) | |
}, once = TRUE, ignoreInit = TRUE, priority = 2) | |
} | |
#------------------------------------------------------- end insert_accordion | |
observeEvent(auto_populate_btn(), { | |
lapply(auto_stack_instructions(), function (battery){ | |
if (!battery %in% current_accordions()){ | |
insert_accordion( | |
battery_name = battery, | |
auto_populate_btn = auto_populate_btn, | |
delete = delete_all, | |
auto_pop_modal | |
) | |
} | |
}) | |
}, priority = 1) | |
} | |
shinyApp(ui, server) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment