TLDR: how to create a timer object to refresh parts across shiny app, this should be a module I can import across the app to keep all things in sync with the ability to pause/edit the interval.
I'm writing a shiny app. In this app I have multiple parts that I want to be updated on an interval.
I'm looking for a way to create a timer object I can use to refresh different parts at a given interval and also a way to pause/change the interval of the reactiveTimer.
I came up with the idea of using a common timer object (setInterval
) in a module (using rhino
and box
) which I import in other modules and use with shiny$observeEvent(timer()...
.
This is the simple timer all it does is trigger every 500ms. Now I want to add the ability to pause and edit the interval.
# Set up a common reactive timer to trigger every 500 ms
common_timer <- shiny$reactiveTimer(interval = 1500)
#' @export
timer <- function() {
return(common_timer())
}
I tried a few different things like making an R6
class to handle the state of my timer (active/inactive); returns timer object or NULL
. But I can't get anything to work properly. My R6
class works but when I pause the timer I can't get it to restart again.
Here is some of my code. Here is an example of how I use the timer for getting some data into my app.
box::use(shiny)
#' @export
live_data <- shiny$reactiveVal(NULL)
#' @export
date_interval <- shiny$reactiveValues(
start_date = lubridate::as_datetime("2019-01-01"),
end_date = lubridate::as_datetime("2019-01-28")
)
box::use(lubridate)
box::use(./common_timer[ timer ])
box::use(./modules/helpers)
box::use(./modules/cpp)
#' @export
call_data <- function(session, side_bar_options) {
shiny$observeEvent(timer$get_timer, {
currency <- shiny$isolate(side_bar_options$currency())
dt <- helpers$read_market_data(
file = "./data/kucoin_btc-usdt-hourly.csv",
symbols = currency,
from = date_interval$start_date,
to = date_interval$end_date
)
live_data(dt)
# bump the dates by 10 days
date_interval$start_date <- date_interval$start_date + lubridate$days(1)
date_interval$end_date <- date_interval$end_date + lubridate$days(1)
})
}
And here is where I want to pause and then after add ability to edit the interval for the timer.
box::use(shiny)
#' @export
ui <- function(id, width = 2) {
ns <- shiny$NS(id)
shiny$sidebarPanel(
shiny$tags$h4("Side bar"),
shiny$selectInput(
inputId = ns("select_currency"),
label = "Currency:",
choices = c("BTC/USDT", "XMR/BTC"),
selected = "BTC/USDT"
),
shiny$selectInput(
inputId = ns("supplementary_plot"),
label = "Supplementary Plot:",
choices = c("RSI", "MACD", "Volume")
),
shiny$actionButton(
inputId = ns("toggle_timer"),
label = "Start/Pause"
),
width = width
)
}
box::use(../logic/common_timer[ timer ])
#' @export
server <- function(id, live_data) {
shiny$moduleServer(id, \(input, output, session) {
ns <- session$ns
shiny$observeEvent(input$toggle_timer, {
timer$toggle_timer()
})
supplementary_plot <- shiny$reactive({
input$supplementary_plot
})
currency <- shiny$reactive({
input$select_currency
})
return(list(
currency = currency,
supplementary_plot = supplementary_plot
))
})
}
Any help would be appreciated. Thank you very much.