Do you ever make a Shiny app and think: Didn’t I just do all this
stuff last week? From creating data upload forms to generating a UI for
building ggplot figures there are certain components we all use in our
apps. The purpose of formods
is to create customizable
Shiny modules to allow many of these components to be created quickly so
you can focus on the part of the app that is unique and interesting.
Each of the modules in formods
generates code dynamically
to produce the underlying outputs. This allows modules combined under
this framework to generate code that allows the state of apps to be
reproduced as a single script.
Each module will have a short name that is used with functions and
namespaces. For example the upload data module would use UD. To use a
module you need to create the appropriate UI elements as well as call
the module server. Both the high level formods
components
and the individual modules are configured through YAML configuration
files.
The currently available modules are listed in the table below. The SN column contains the short name used to identify that module. The individual HTML UI elements are listed as well as other UI outputs.
Module | SN | htmlOutput | Other Outputs |
---|---|---|---|
App State Mangement | ASM | ui_asm_save_name, ui_asm_save_button, ui_asm_load_state | ui_asm_msg, ui_asm_ace_code |
Upload Data | UD | ui_ud_load_data, ui_ud_select_sheets, ui_ud_text_load_result, ui_ud_data_preview | ui_ud_ace_code |
Data Wrangling | DW | ui_dw_views, ui_dw_key, ui_dw_new_view, ui_dw_save_view, ui_dw_del_view, ui_dw_copy_view, ui_dw_add_element_button, ui_dw_select, ui_dw_new_element_row | hot_dw_elements, hot_data_preview, ui_dw_msg, ui_dw_code |
Figure Generation | FG | ui_fg_curr_views, ui_fg_curr_figs, ui_fg_new_fig, ui_fg_save_fig, ui_fg_del_fig, ui_fg_copy_fig, ui_fg_fig_name, ui_fg_fig_notes, ui_fg_add_element_button, ui_fg_select, ui_fg_new_element_row, ui_fg_msg, ui_fg_slider_page | hot_fg_elements, ui_fg_preview_ggplot, ui_fg_msg, ui_fg_code |
Using a module requires two components: You need to add UI elements
for those in the module, and then you need to add the server component
as well. Take care to use the same id
for both the UI and
server components. The UI elements are listed in the table above. Also
each module in formods
contains an example App file which
isolates each UI component to allow you to see how it’s used. This is
called XX_module_components.R
, where XX
is the
module short name. For example to see an example of the upload data
module you could run the following to copy the file locally:
copy.file(system.file(package="formods", "templates", "UD_module_components.R"), "UD_module_components.R")
If you want to run the App from within the package you can just do the following:
Using the module components script above, you can see whate each UI
element looks like and how it behaves. This allows you to have granular
control over the UI elements and their placement. For each module,
formods
provides a single ui output to place all of the
module UI components together. For the upload data module it looks like
this:
If you copy the FM_compact.R
file locally, you can see
how these are used for each module:
And you can run this example and see how the modules interact as well:
To deploy your App you need to create an App file with the
appropriate ui
and server
functions called
App.R
. This will create one for you:
There are certain aspects of the app that behave differently when
deployed. To do that you need to indicate that the app is deployed. You
can do this in two ways. This is done by setting the
deployed
argument to each of the server functions to
TRUE
.
Each module has a server function that uses the shortname followed by
an underscore as the prefix. For example the server function named using
the convention: XX_Server()
. Where XX
is the
module short name. For example the server function for the upload data
module is UD_Server()
. At a minimum the server will take
the module ID, a configuration file for the formods package, the module
configuration file, and reactive object called react_state
.
The react_state
object is used to link reactions between
the modules.
Again the the different XX_module_components.R
files
shows how to use the server functions for each module. Briefly, using
the UD module as an example you would do the following in your app
server
function:
Both formods
and the individual modules are configured
through YAML files. By default, the modules will use the included
template YAML files. However, you may want to alter the default
formatting and text. To do that you simply need to make local copies of
the files like this:
copy.file(system.file(package="formods", "templates", "formods.yaml"), "formods.yaml")
copy.file(system.file(package="formods", "templates", "UD.yaml"), "UD.yaml")
You can then modify those files. To use them you need to point the server functions to those instead of the default templates. The following sections describe the current modules and how to use them.
The ASM module is used to manage the app state. This allows the user to save the current app state and load it at a later time.
The UD module allows users to upload data files into the App. It will allow you to specify file types and for Excel files the sheet to be used.
Provides
FM_fetch_ds()
The DW module provides an interface to dplyr
and
tidyr
.These are used to create chains of data wrangling
commands that the user can build to transform the data creating
data views. The DW module can use data from the UD
module, or can take in a list with a dataset.
Provides
FM_fetch_ds()
The FG module provides an interface to ggplot
and allows
the user to select from both the original data set from the UD module as
well as the data views created in the DW module. The user here can
create multiple figures.
Provides
If you are running RStudio on a server (through a web browser) and you receive the following message:
413 Request Entity too large.
The problem lies in the NGINX server. This is a proxy server being
used by RStudio. And the issue is a limit on the maximum upload size in
the NGINX server. The solution is to edit the configuration file
(something like /etc/nginx/nginx.conf
) and set the option
client_mx_body_size
to something more reasonable.