knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)

As a reminder, the namespace is an important aspect of shiny module that prevents collision of input and output IDs in your application. The namespace identify each unique instance of the modules and need to be provided by the caller.

{tidymodules} can be considered as an object-oriented organisational layer on top of shiny that does conventional module in the background. It does use namespace but make it optional to the users. In other words, you don't need to remember it!

Optional namespace Id

In the example below a {tm} module MyMod is defined and called with the new() function and with no arguments supplied.
Printing the instance m to the console shows the structure of the module.

library(tidymodules)

MyMod <- R6::R6Class(
  "MyMod",
  inherit = TidyModule
)

m <- MyMod$new()

m

The namespace Id for module m above is MyMod-1. It is a unique Id generated by {tidymodules} and composed of the class name and the initialisation order of the module.

User defined namespace Id

The user can also provide a more informative name when initialising a module.

m <- MyMod$new("Tom")

m

Tom end up being the namespace Id of m.

The provided name must begin with a letter [A-Za-z] and may be followed by any number of letters, digits [0-9], hyphens -, underscores _. You should not use the following characters as they have a special meaning on the UI ( CSS / jQuery ).

~ ! @ $ % ^ & * ( ) + = , . / ' ; : " ? > < [ ] \ { } | ` #

Namespace and nested modules

The code below illustrates a very simple example of nested module and the corresponding namespace Ids. Here are few things to note about this example:

ModB <- R6::R6Class(
  "ModB",
  inherit = TidyModule
)

ModA <- R6::R6Class(
  "ModA",
  inherit = TidyModule,
  public = list(
    nested_mod = NULL,
    initialize = function(...) {
      super$initialize(...)
      self$nested_mod <- ModB$new()
    }
  )
)

m <- ModA$new()
n <- m$nested_mod

m
n

Grouping modules

This option allows the grouping of {tm} modules together to facilitate their retrieval from the ModStore and to better visualize them later in a network diagram.

ta <- MyMod$new("Tom", group = "A")
tb <- MyMod$new("Tom", group = "B")

ta
tb

As you can see above the group argument is used to define the final namespace Id of the modules. Those modules share the same name but have different namespace IDs.

module's IDs and UI function

A {tm} module namespace is a concatenation of many fields.

the module's namespace is built like this

id = <group>_<name>
module_ns = <parent_ns>_<id>
#' @field name Name of the module, either generated for or provided by the user.
n$name
ta$name

#' @field group Group name of the module.
n$group
ta$group

#' @field id ID of the module.
n$id
ta$id

#' @field parent_ns Parent module namespace in case of nested modules.
n$parent_ns
ta$parent_ns

#' @field module_ns Module namespace, unique identifier for the module.
n$module_ns
ta$module_ns

Like in conventional module, {tm} module also requires wrapping UI elements with the namespace. The function named ns() available in all {tm} modules should be used to namespace the inputs. As you can see in the example below, you simply need to call the function using the self R6 keyword. There is no need to remember the modules's namespace anymore.

MyMod <- R6::R6Class(
  "MyMod",
  inherit = TidyModule,
  public = list(
    ui = function() {
      shiny::tagList(
        shiny::numericInput(self$ns("inputId"), NULL, 0)
      )
    }
  )
)

m <- MyMod$new()
as.character(m$ui())

ModStore and module lookup

The ModStore is an internal repository for all {tm} modules and connections (see communication article for learning how to connect modules). It is a shared environment created by {tidymodules} that orginizes the objects (modules and edges) by applications and sessions. This allows to track and easily retrieve the modules anywhere in the application.

All the examples above show the creation of modules with the new() R6 function and the assignment to variables (pointers to the R6 objects). However {tidymodules} also offers the choice to not save module references and instead use the getMod() or mod() utility functions to retrieve existing module. Note that mod() is just an alias of getMod().

MyMod$new("SaveMeInStore")

# look-up by namespace ID
mod("SaveMeInStore")

# look-up by index
mod(2)

# look-up by index within a group
mod(1, group = "A")


Novartis/tidymodules documentation built on Feb. 27, 2023, 8:35 a.m.