diff --git a/vignettes/data-as-shiny-module.Rmd b/vignettes/data-as-shiny-module.Rmd index 7b3da971b9..5fb7ce9d30 100644 --- a/vignettes/data-as-shiny-module.Rmd +++ b/vignettes/data-as-shiny-module.Rmd @@ -1,31 +1,42 @@ --- -title: "Data as shiny module" +title: "Data as shiny Module" author: "NEST CoreDev" output: rmarkdown::html_vignette: toc: true vignette: > - %\VignetteIndexEntry{Data as shiny module} + %\VignetteIndexEntry{Data as shiny Module} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ## Introduction -For the proper functioning of any `teal` application, the presence of a `teal_data` object is essential. Usually, application developers provide the `teal_data` object created within the `.GlobalEnv` environment as an argument for the `data` parameter. This `teal_data` object should encompass the required elements necessary for successful execution of the application's modules. In certain scenarios, application developers may opt to defer specific data operations by assigning a shiny module to the data parameter, allowing `teal` to execute the module every time a new session starts. +Proper functioning of any `teal` application requires presence of a `teal_data` object. +Typically, a `teal_data` object created in the global environment will be passed to the `data` argument in `init`. +This `teal_data` object should contain all elements necessary for successful execution of the application's modules. +In some scenarios, however, application developers may opt to postpone some data operations until the application run time. +This can be done by passing a special _`shiny` module_ to the `data` argument. +The `teal_data_module` function is used to build such a module from the following components: -## Postponed data creation +- a `ui` function; accepts only one argument, `id`; defines user interface elements for the data module +- a `server` function: accepts only one argument, `id`; defines server logic for the data module, including data creation; must return a reactive expression containing a `teal_data` object -In scenarios where certain data must be created anew each time a user opens the app, such as when the data is dynamic and frequently changing, loading the data once in the `.GlobalEnv` is not suitable. Instead, teal can generate the necessary objects each time a new session begins by specifying the `teal_data_module` using the following components: +`teal` will run this module when the application starts and the resulting `teal_data` object that will be used throughout all `teal` (analytic) modules. -- `ui` Function: This function should accept an `id` argument and define the user interface elements for the data module. +## Creating Data In-App -- `server` Function: Similarly, the server function should accept an `id` argument and define the server logic for the data module. `moduleServer` should return a reactive `teal_data` object, which will be used by the application to ensure the availability of up-to-date data upon each session start. +One case for postponing data operations are data sets that are dynamic, frequently updated. +Such data cannot be created once and kept in the global environment. +Using `teal_data_module` allows to create a data set from scratch every time the user starts the application. +This the user will always have access to the most recent version of the data. + +```{r, message = FALSE, warning = FALSE} +library(teal) +``` -By following these requirements, teal can efficiently handle dynamic data updates and create the necessary objects for a seamless user experience. ```{r} -library(teal) data_mod <- teal_data_module( ui = function(id) div(), server = function(id) { @@ -57,11 +68,12 @@ if (interactive()) { ``` -## Postponed data modification +## Modification Data In-App -In certain scenarios, app developers may want to pre-create a `data` object before a `teal` session initializes, allowing app users to interact with this `data` from the session's start. This can be achieved by using the `teal_data_module` function to efficiently modify the existing data object. +Another reason to postpone data operations is to allow the application user to act the preprocessing stage. +An initial, constant form of the data can be created in the global environment and then modified once the app starts. -The following code snippet illustrates how teal_data_module can be utilized to subset the `dataset1` based on the selected `Species` from the `input$species` variable: +The following example illustrates how `teal_data_module` can be utilized to subset data based on the user inputs: ```{r} data <- within(teal_data(), { @@ -74,7 +86,8 @@ data_mod <- teal_data_module( ui = function(id) { ns <- NS(id) div( - selectInput(ns("species"), "Select species to filter", choices = unique(iris$Species), multiple = TRUE), + selectInput(ns("species"), "Select species to filter", + choices = unique(iris$Species), multiple = TRUE), actionButton(ns("submit"), "Submit") ) }, @@ -102,4 +115,12 @@ if (interactive()) { } ``` -It's important to note that this approach reduces app loading time as `data` creation in the `.GlobalEnv` only involves data transformation. However, it's crucial to ensure that the initial server function is defined in the same environment as the data object to enable this functionality. This requirement ensures that data exists in the same environment as the calling environment of the `server` function, allowing for efficient data modification and interaction. +_See `?within.qenv` for a detailed explanation of how to use the `within` method._ + +Note that running preprocessing code in a module as opposed to the global environment will increase app loading times. +It is recommended to keep the constant code in the global environment and to move only the dynamic parts to a data module. + +###### WARNING + +When using `teal_data_moduel` to modify a pre-existing `teal_data` object it is crucial that the server function and the data object are defined in the same environment as otherwise the server function will not be able to access the data object. +This means server functions defined in packages cannot be used.