Module Decorator Class
ShinyModule.RdThis class is a decorator and is not meant to be directly used, but to be
inherited by other Modules.
Details
Namespacing
The ShinyModule class manages namespacing with the moduleName and
instanceId, to create a moduleId. The moduleId and parentNamespace
(when a module is nested in another module) make up the namespace field.
moduleId = moduleName-instanceId
namespace = [parentNamespace-]moduleId
Server method
When creating a new module, the id in shiny::moduleServer() is set to
the moduleId field.
Besides setting the id, the initServer() method is called at the start of
shiny::moduleServer(). This initializes a reactive environment to be used
freely when developing modules. This method may be expanded upon to
initialize other namespace dependant features.
All of this is done by the class it self, in the public server() method.
The server() method calls the private private$.server(), which should
overridden when creating a module.
As an example:
...
private = list(
.server = function(input, output, session) {
output$table <- shiny::renderTable(iris)
}
)
...If the public server() method is overridden an error will be thrown:
...
public = list(
server = function(input, output, session) {
output$table <- shiny::renderTable(iris)
}
)
...
myModule <- MyModule$new()
#> `self$server()` was overridden in `public = list(...)` override `private$.server()` instead in `private = list(.server = function(input, output, session) {})`UI method
When accessing an outputId in the UI, the namespace field is used to
reference the correct namespace with shiny::NS().
It is also expected that the UI() method returns all contents to be shown,
so if multiple things should be shown, they should be nested in, as an
exmaple, shiny::taglist().
As an example:
...
private = list(
.UI = function() {
# `private$.namespace` would also be valid.
shiny::tableOutput(outputId = shiny::NS(self$namespace, "table"))
}
)If the public UI() method is overridden an error will be thrown:
...
public = list(
server = function(input, output, session) {
output$table <- shiny::renderTable(iris)
}
)
...
myModule <- MyModule$new()
#> `self$UI()` was overridden in `public = list(...)` override `private$.UI()` instead in `private = list(.UI = function() {})`Active bindings
instanceId(
character(1)) Random ID of 10 capitalized letters.parentNamespace(
character(1)) Namespace of the parent module.moduleName(
character(1)) Name of the module.moduleId(
character(1)) Module identifier, composed like:moduleName-instanceIdnamespace(
character(1)) Namespace, composed like:[parentNamespace-]moduleName-instanceIdwhereparentNamespaceis optionalreactiveValues(
reactivevalues) Reactive values. useshiny::isolate()to get a non-reactive item from the reactive environment.async(
logical(1):FALSE) Logical parameter to switch asynchronous mode on or off.
Methods
Method UI()
Method to include a tagList to include the body.
Method server()
Method to handle the back-end.
Examples
MyModule <- R6::R6Class(
classname = "MyModule",
inherit = ShinyModule,
private = list(
.UI = function() {
# `private$.namespace` would also be valid.
shiny::tableOutput(outputId = shiny::NS(self$namespace, "table"))
},
# Override server()
.server = function(input, output, session) {
output$table <- shiny::renderTable(iris)
}
)
)
if (interactive()) {
myModule <- MyModule$new()
preview(myModule)
}
# The following would throw an error for overwritnig the public UI() and server() methods:
MyModule <- R6::R6Class(
classname = "MyModule",
inherit = ShinyModule,
public = list(
UI = function() {
# `private$.namespace` would also be valid.
shiny::tableOutput(outputId = shiny::NS(self$namespace, "table"))
},
# Override server()
server = function(input, output, session) {
output$table <- shiny::renderTable(iris)
}
)
)
tryCatch(
{
myModule <- MyModule$new()
},
error = function(e) {
message(e)
}
)
#> Error in private$checkMethodOverrides(): `self$server()` was overridden in `public = list(...)` override `private$.server()` instead in `private = list(.server = function(input, output, session) {})`
#> `self$UI()` was overridden in `public = list(...)` override `private$.UI()` instead in `private = list(.UI = function() {})`
#> `self$server()` was overridden in `public = list(...)` override
#> `private$.server()` instead in
#> `private = list(.server = function(input,output, session) {})`
#> `self$UI()` was overridden in `public = list(...)` override
#> `private$.UI()` instead in `private = list(.UI = function() {})`