3MW (Using Shiny Modules With Golem)

Guten Tag!

Many greetings from Munich, Germany. This week, we are going to dive deeper into the Golem framework. Specifically, I’m going to show you the workflow of creating and adding modules inside your Golem app. But first, time for my regular announcements.

How to deal with blank line charts

Ever wanted to create a line chart with {ggplot2} only to find that the chart is empty? This happens when you try to use a non-numeric variable as x- or y-aesthetic and don't specify the group aesthetic.

In those cases, ggplot even tells you that you probably need to set the group aesthetic. And in my newest YT video, I show you exactly how that works:

As always, you can find all the code that I show you on GitHub.

Create a module

As we’ve learned a couple of weeks ago, it’s good practice to structure your app into Shiny modules. The easiest way to do that is to manually navigate to our R/dev.R file of the Golem app we’ve created last week. Alternatively, you could open this also very easily with the command palette:

There, we can use the golem::add_module() function to create a module with the name of our choosing.

Once we execute this, Golem will be kind enough to create two files for us:

  1. A file called mod_<module_name>.R inside the R directory.

  2. A test file inside the tests directory of our package.

For now, you can ignore the test thing. This is something about unit tests, which we’ll talk about some other time. I want to focus on the module file here.

Module Structure

Inside the module file, there are more or less two things. First, there’s the module UI function:

Second, there’s the corresponding server function:

Both functions are decorated with a whole bunch of extra notation which allows for describing what this function does. This is how packages and documentations for functions are built. For now, you can just ignore this. All you have to know is that you can use your knowledge about modules inside the module function that we’ve just created.

And a little convenient tidbit: At the bottom of that file, you see that you’re already provided with code that you can copy into app_ui.R and app_server.R to use your new module.

Testing Modules

What you can do now is to

  • fill the UI with the things we’ve put into app_ui.R last week and

  • wrap the ID into the ns() function.

And into the module server we put in the things that we used in app_server.R last week.

Now, I don’t want you to put the module calls into the full app just yet. First, I want to demonstrate how you can use the Golem structure to use the philosophy of small modules. You know, the thing we’ve covered a couple of newsletters ago.

Inside the script that already contains the module code, you can add code that creates a Shiny app. If you throw in a Shiny app in there, you can just stick in your module and execute this whole script. That way, you can just test your one module.

The cool thing about this is that if you later call golem::run_app(), this extra tiny app that tests only the module is ignored. Instead, Golem will just create the app that you specified in the app_ui.R and app_server.R scripts.

Handling Packages in a Golem App

Before I let you run off and play with Golem on your own time, let me highlight one thing about packages inside your Golem app. If you want to use functions from, say, the Tidyverse, you will have to load the package somehow. There are more or less three ways to do that:

  1. You could always use the full name of a function. For example, if you want to use mutate() from {dplyr} in your code, you’ll have to write out dplyr::mutate().

  2. Inside the function where you want to use, say, mutate(), you could add mutate() to the #' @importFrom call that you already see in the template that Golem gave you. You know, that one line from your module UI skeleton:

In our mutate() example, you could do the exact same thing by adding another @importFrom statement in front of that function and specifying @importFrom dplyr mutate.

  1. Or if you want to load all of dplyr, you could just throw in an @import dplyr statement.

This is one of the occasions where using Golem comes with a bit of overhead and additional struggle. Admittedly, this type of coding might feel weird to you at first, but you can get used to this quite quickly. In the long run, adopting this style helps to create a robust Shiny app.

With that, you should have everything to get started creating modules for your Golem app. Next week, I’m going to talk a little bit more about workflow with Golem. And if you have any questions, don’t hesitate to reply to this mail or contact me on LinkedIn.

See you next week,
Albert 👋

Enjoyed this newsletter? Here are other ways I can help you:


or to participate.