I am learning to use R6 in a Shiny app with the aim of separating the logic from the app.
I have a question about the value of the initialize
function in the R6 class.
As shown in the reproducible example below, I have defined name = 'Eric'
and set up the initialize
function to assign ‘Eric’
as the default value of name
. Why is ‘Eric’
not displayed when the app is launched?
library(shiny)
library(R6)
library(gargoyle)
# R6 object -----------------------------------------------------------------------------
ExampleR6 <- R6Class(
classname = "example",
public = list(
name = "Eric",
initialize = \(name = "Eric") {
self$name <- name
}
))
# Module 1 ------------------------------------------------------------------------------
mod_1_UI <- function(id) {
ns <- NS(id)
tagList(
textInput(inputId = ns("input_name"), label = "What's your name?")
)
}
mod_1_Server <- function(id, r6) {
moduleServer(
id,
function(input, output, session) {
observeEvent(input$input_name, {
r6$name <- input$input_name
trigger("change_name")
})
}
)
}
# Module 2 ------------------------------------------------------------------------------
mod_2_UI <- function(id) {
ns <- NS(id)
tagList(
textOutput(outputId = ns("output_name"))
)
}
mod_2_Server <- function(id, r6) {
moduleServer(
id,
function(input, output, session) {
observeEvent(watch("change_name"), {
output$output_name <- renderText(r6$name)
})
}
)
}
# Main app ------------------------------------------------------------------------------
ui <- fluidPage(
mod_1_UI(id = "mod_1"),
mod_2_UI(id = "mod_2")
)
server <- function(input, output, session) {
hello_r6 <- ExampleR6$new()
init("change_name")
mod_1_Server(id = "mod_1", r6 = hello_r6)
mod_2_Server(id = "mod_2", r6 = hello_r6)
}
shinyApp(ui, server)
There is a lot more going on in your MRE than just using R6. I'm not sure what you're trying with the initialize =
part - setting name = "Eric"
is sufficient and you can tell that by printing hello_r6$name
in the main server. The reason your MRE doesn't work is that you are overwriting the initial value in mod1
with r6$name <- input$input_name
. If you wrap that like this it will work as expected:
if (input$input_name != ""){
r6$name <- input$input_name
}
Putting output
inside observeEvent
is not best practice. This is a better alternative to achieve the same result with {gargoyle}
:
output$output_name <- renderText({
watch("change_name")
r6$name
})