'Why is updateTabsetPanel running last inside an observeEvent?
I am looking to:
- Insert UI elements
- Update UI elements
- Run a long calculation
All after pressing one button. Example app:
#EXAMPLE APP----
#Libraries----
library(shiny)
library(shinyjs)
#UI code----
ui <- fluidPage(
useShinyjs(),
mainPanel(
tabsetPanel(
id = "test",
tabPanel(
title = "First",
actionButton(
"press",
"Press Me")),
tabPanel(
title = "Second",
tabsetPanel(
id = "toinsert"
)))
)
)
#Server code----
server <- function(input, output, session) {
##Disable as default Second tab----
observe({
disable(selector = '#test a[data-value = "Second"]')
})
##Enable select 2ndtab and insert-select tab inside----
totest <- reactiveValues()
totest$tab <- 0
observeEvent(input$press,{
enable(selector = '#test a[data-value = "Second"]')
updateTabsetPanel(
session,
'test',
selected = "Second"
)
totest$tab <- totest$tab + 1
insertTab(
session = session,
inputId = "toinsert",
tab = tabPanel(
title = paste0("AA_",totest$tab),
div(p("BBBBB"))
)
)
updateTabsetPanel(
session,
'toinsert',
selected = paste0("AA_",totest$tab)
)
totest$a <- 1
})
##Running long calculation once proper tab is selected(not working)----
observeEvent(totest$a,{
if(totest$a == 1){
Sys.sleep(5)
print("A")
totest$a <- 0
}else{}
})
}
shinyApp(ui, server)
Running the previous example you will notice that the code runs correctly but out of order: running the calculation first and updating UI elements after. Searching on stackoverflow I found a similar question R shiny: Update tabsetpanel before finishing all the observeEvent code and tried the accepted answer changing my observeEvent code to:
observeEvent(input$press,{
enable(selector = '#test a[data-value = "Second"]')
updateTabsetPanel(
session,
'test',
selected = "Second"
)
totest$tab <- totest$tab + 1
insertTab(
session = session,
inputId = "toinsert",
tab = tabPanel(
title = paste0("AA_",totest$tab),
div(p("BBBBB"))
)
)
updateTabsetPanel(
session,
'toinsert',
selected = paste0("AA_",totest$tab)
)
givingvalue <- reactive({
req(input$toinsert)
totest$a <- 1
})
givingvalue()
})
But this didn't work. After clicking the button for the first time the UI is updated but the long calculation didn't run and after I press the button for the second time it works as previous configuration. I assume is running the calculation after button is clicked again.
Why is this happening? How could I fix my problem?
Solution 1:[1]
As I said on the comments of YBS's answer what actually worked for me was changing the second observeEvent to check on input$toinsert instead of totest$a. Being the final code as follow.
#EXAMPLE APP----
#Libraries----
library(shiny)
library(shinyjs)
#UI code----
ui <- fluidPage(
useShinyjs(),
mainPanel(
tabsetPanel(
id = "test",
tabPanel(
title = "First",
actionButton(
"press",
"Press Me")),
tabPanel(
title = "Second",
tabsetPanel(
id = "toinsert"
)))
)
)
#Server code----
server <- function(input, output, session) {
##Disable as default Second tab----
observe({
disable(selector = '#test a[data-value = "Second"]')
})
##Enable select 2ndtab and insert-select tab inside----
totest <- reactiveValues()
totest$tab <- 0
observeEvent(input$press,{
enable(selector = '#test a[data-value = "Second"]')
updateTabsetPanel(
session,
'test',
selected = "Second"
)
totest$tab <- totest$tab + 1
insertTab(
session = session,
inputId = "toinsert",
tab = tabPanel(
title = paste0("AA_",totest$tab),
div(p("BBBBB"))
)
)
updateTabsetPanel(
session,
'toinsert',
selected = paste0("AA_",totest$tab)
)
totest$a <- 1
})
##Running long calculation once proper tab is selected(working)----
observeEvent(input$toinsert,{
if(totest$a == 1){
Sys.sleep(5)
print("A")
totest$a <- 0
}else{}
})
}
shinyApp(ui, server)
Solution 2:[2]
Perhaps you are looking for this
ui <- fluidPage(
useShinyjs(),
mainPanel(
tabsetPanel(
id = "test",
tabPanel(
title = "First",
actionButton(
"press",
"Press Me")),
tabPanel(
title = "Second",
tabsetPanel(
id = "toinsert"
)))
)
)
server <- function(input, output, session) {
# observe({
# disable(selector = '#test a[data-value = "Second"]')
# })
totest <- reactiveValues(tab=0,a=0)
observeEvent(input$press,{
#enable(selector = '#test a[data-value = "Second"]')
totest$tab <- totest$tab + 1
updateTabsetPanel(
session,
'test',
selected = "Second"
)
})
observeEvent(input$test,{
print(input$test)
#totest$a <- 1
if (input$test=="Second") {
insertTab(
session = session,
inputId = "toinsert",
tab = tabPanel(
title = paste0("AA_",totest$tab),
div(p("BBBBB"))
)
)
updateTabsetPanel(
session,
'toinsert',
selected = paste0("AA_",totest$tab)
)
}
})
observeEvent(input$toinsert,{
if (!is.null(input$toinsert)) {
Sys.sleep(5)
print("A")
}
}, ignoreNULL = TRUE)
}
shinyApp(ui, server)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | David Díaz |
Solution 2 |