This vignette will guide you through implementation of custom ggplot2::labs
and ggplot2::theme
for ggplot2
graphics
based modules.
We will enable 2 ways of updating ggplot2::labs
and ggplot2::theme
by the end users.
The ggplot2
specification could be updated with the teal.ggplot2_args
options
variable or a ggplot2_args
argument in a tm_g_*
module. We still take into account default specification set up by the module creator in the
server function, which has the lowest priority.
The implementation should consist of 5 steps:
ggplot2_args
argument to the tm_g_*
function and then its server function. The default should be set to
the ggplot2_args(labs = list(), theme = list())
function for single plot.
and list(default = ggplot2_args(labs = list(), theme = list()))
multi-plot modules.stopifnot
or checkmate
) of the ggplot2_args
argument to the tm_*
function.
The validation is more complex for multi-plot modules, where the ggplot2_args
could be a list
.
The module creator has to provide a list of plots names, which should be validated at this step and added to the param
field in roxygen2
.
For multi-plot modules the step if (is_ggplot2_args) ggplot2_args <- list(default = ggplot2_args)
is recommended.ggplot2_args
sources with resolve_ggplot2_args()
.parse_ggplot2_args()
function which will parse inputs
to list of expressions.Reduce(function(x, y) call("+", x, y), list(...)
function could be helpful at this step.The resolve_ggplot2_args()
function picks the first non NULL value for each argument, checking in order:
ggplot2_args
argument provided by the end user.
For multi-plot case, per plot (user_plot
) and then default (user_default
) setup.options
), teal.ggplot2_args
.module_plot
which is a developer setup.When a more complex ggplot2
object has to be used inside the teal.widgets::ggplot2_args
function, then a base::quote
function would prevent an object expansion in Show R Code. For example the ggplot2::element_text
function returns a
complex object, then we should use code like
teal.widgets::ggplot2_args(theme = list(plot.title = quote(ggplot2::element_text(size = 20))))
to prevent Show R Code
expansion.
If you get a promise already under evaluation: recursive default argument reference or earlier problems?
error, then
probably your function argument has the same name as a function which is an input for it.
To solve the problem please use ::
to prefix it directly to a specific package, like
new_fun <- function(ggplot2_args = teal.widgets::ggplot2_args())
.
library(shiny) library(ggplot2) library(teal.widgets) options("teal.ggplot2_args" = teal.widgets::ggplot2_args(labs = list(caption = "Caption from options"))) user_ggplot2_args <- list( default = ggplot2_args( labs = list(title = "User default title"), theme = list(legend.position = "right", legend.direction = "vertical") ), plot1 = ggplot2_args( labs = list(title = "User title"), theme = list(legend.position = "right", legend.direction = "vertical") ) ) app <- shinyApp( ui = fluidPage( shinyjs::useShinyjs(), div(plotOutput("plot1")) ), server = function(input, output, session) { dev_ggplot2_args <- ggplot2_args( labs = list(subtitle = "Dev substitle"), theme = list(legend.position = "none") ) f_ggplot2_expr <- parse_ggplot2_args( resolve_ggplot2_args( user_plot = user_ggplot2_args$plot1, user_default = user_ggplot2_args$default, module_plot = dev_ggplot2_args ) ) plot_expr <- substitute( expr = { gg <- ggplot(iris, aes(x = Sepal.Length, y = Petal.Length, color = Species)) + geom_point() + ggplot_expr_labs + ggplot_expr_theme print(gg) }, env = list(ggplot_expr_labs = f_ggplot2_expr$labs, ggplot_expr_theme = f_ggplot2_expr$theme) ) print(plot_expr) output$plot1 <- renderPlot(eval(plot_expr)) } )
shinyApp(app$ui, app$server)
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.