0

I have quite an interesting problem. I have a number of checkboxes for input in Shiny (naturally), everything works fine, if I click a checkbox and wait like half a second and click the next (the screen dims to grey and then the checkbox is checked and the I can continue). However, if I check a checkbox without waiting (just before the screen goes grey) shiny ends up in an infinite loop.

I cannot give the full code, but the just of it is provided.

obs_ev <- "c(input[['cbox_gr1']], input[['cbox_gr2']]")

observeEvent(eval(parse(text = obs_ev)), {

dat <- eval(parse(text = obs_ev))
v1  <- input$v2
v2  <- v2_short_list[v2_list == input$v2]

# Only need the first one since v1 and v2 are the same for all inputs
dat_temp <- dat[1]

# Dataframe to update
v1_updt <- gsub("_-_", "\\2", dat_temp)
v2_updt <- gsub("_-_", "\\3", dat_temp)

focused.df      <- paste0(gsub(" ", "_", v1), "_", v2)
working.df.name <- paste0(v1_updt, "_", v2_updt)

if (focused.df == working.df.name) {

  print(dat)

  # V3 to update
  v3_updt <- gsub("_-_", "\\1", dat_temp)

  reactive.df.name <- paste0(v1_updt, "_", v2_updt, "_react")

  # Rows to update
  rows_updt <- as.numeric(gsub("_-_", "\\4", dat))

  # Update data based on checkbox input
  eval(parse(text = paste0("temp_updt <- ", working.df.name)))
  tbc <- temp_updt[[v3_updt]][!temp_updt$key %in% rows_updt]
  tbc[tbc == 2] <- 1
  temp_updt[[v3_updt]][!temp_updt$key %in% rows_updt] <- tbc
  temp_updt[[v3_updt]][rows_updt] <- 2

  # Overwrite the dataframe (not the reactive one, but instead the one that the reactive dataframe is linked to)
  eval(parse(text = paste0(working.df.name, " <<- temp_updt")))
}
})

Again, the code is working just fine, except for the delay in the click - the fact that Shiny 'fades' in and out when I click on a checkbox, even more, the fade doesn't bother me that much (I would like it gone though) the fact that if I click before the fade, the whole thing ends up in a loop

  • one cant see the whole app, but looks like you could to a look at `isolate()`,... – Tonio Liebrand Jun 19 '17 at 09:13
  • unfortunately I cannot share the whole app - but thanks for the tip! I will have a look at isolate and let you know if it works :) I haven't used this before – Charl Francois Marais Jun 19 '17 at 09:15
  • @CharlFrancoisMarais, do check [dangers of eval(parse(...))](https://stackoverflow.com/questions/13649979/what-specifically-are-the-dangers-of-evalparse) – parth Jun 19 '17 at 09:24
  • @ParthChaudhary thanks, indeed I try to avoid this command, but in my case I can't see any other solution as I have a variable amount of checkboxes (in the 100's) this seems like the most natural way of handling this amount of checkboxes – Charl Francois Marais Jun 19 '17 at 09:46
  • @CharlFrancoisMarais, you can also create a global variable `working.df.name` and assign it with `working.df.name <- temp_updt` rather than `eval(.....)` – parth Jun 19 '17 at 10:03

1 Answers1

0

I've run into similar situations when the time it takes to update all of the reactives is somewhat long and changing the inputs triggers some kind of circularity. I've not always been able to resolve what is causing it. In several cases, I've given up and just disabled the input controls so that I don't have the option of changing the inputs before the current update is finished.

You will need to use the shinyjs package and include the useShinyjs() function in your ui file.

I would adapt your code as follows:

observe({
  ctrl <- paste0("cbox_gr", 1:2)

  lapply(ctrl,
         function(x){

           observeEvent(
             input[[x]], {

               ## DISABLE INPUT CONTROLS HERE
               lapply(ctrl, disable)

               dat <- eval(parse(text = obs_ev))
               v1  <- input$v2
               v2  <- v2_short_list[v2_list == input$v2]

               # Only need the first one since v1 and v2 are the same for all inputs
               dat_temp <- dat[1]

               # Dataframe to update
               v1_updt <- gsub("_-_", "\\2", dat_temp)
               v2_updt <- gsub("_-_", "\\3", dat_temp)

               focused.df      <- paste0(gsub(" ", "_", v1), "_", v2)
               working.df.name <- paste0(v1_updt, "_", v2_updt)

               if (focused.df == working.df.name) {

                 print(dat)

                 # V3 to update
                 v3_updt <- gsub("_-_", "\\1", dat_temp)

                 reactive.df.name <- paste0(v1_updt, "_", v2_updt, "_react")

                 # Rows to update
                 rows_updt <- as.numeric(gsub("_-_", "\\4", dat))

                 # Update data based on checkbox input
                 eval(parse(text = paste0("temp_updt <- ", working.df.name)))
                 tbc <- temp_updt[[v3_updt]][!temp_updt$key %in% rows_updt]
                 tbc[tbc == 2] <- 1
                 temp_updt[[v3_updt]][!temp_updt$key %in% rows_updt] <- tbc
                 temp_updt[[v3_updt]][rows_updt] <- 2

                 # Overwrite the dataframe (not the reactive one, but instead the one that the reactive dataframe is linked to)
                 eval(parse(text = paste0(working.df.name, " <<- temp_updt")))
               }

               ## ENABLE INPUT CONTROLS HERE
               lapply(ctrl, enable)
             })
         }
  )
})
Benjamin
  • 16,897
  • 6
  • 45
  • 65