I am working on a shiny app and I quickly realized it was going to become pretty large and complex. I began thinking about how it would be great to be able to modularize it and reuse the modules. After some research, I discovered this is possible using shiny modules! I am taking a stab and changing the first iteration of my app to use modules but I am stuck. I have read through all of the articles I can find and watched a few videos, but all of the examples I have found so far build a rather simple app, so I hope someone here is able to help. I have my ui.r, server.r, CFNavbarTab.r, and CFData.r files. I plan to have several navbarMenus with tabPanels so my goal was to modularize as much of the tabPanel as possible. There error I am getting is the
ERROR: Operation not allowed without an active reactive context. (You tried to do something that can only be done from inside a reactive expression or observer.)
so I know I am missing a reactive expression somewhere. I am having trouble with the logic around how to use renderUI for a dynamic selectInput as well as filtering on multiple ui inputs. Here is the code so far:
ui.r
library(shiny)
library(DT)
library(shinythemes)
source("CFNavbarTab.r")
source("CFData.r")
shinyUI(fluidPage(shinythemes::themeSelector(),
titlePanel("Cluster Capacity Dashboard"),
navbarPage("NavBar",
navbarMenu("RAM",
tabPanel("Availability Difference (Large)", CFNavbarTabUI("ram.lg"))
)
)
)
)
server.r
library(shiny)
library(dplyr)
library(ggplot2)
library(reshape2)
source("CFNavbarTab.r")
source("CFData.r")
shinyServer(function(input, output) {
callModule(CFNavbarTab, "ram.lg", reactive(ram.lg.data))
})
CFData.r
library(dplyr)
# Data import
setwd("~/TDP/CPF_Analytics/CapacityForecasting/Version2")
k8s_ram_cpu_report <- read.csv("k8s_ram_cpu_report.csv")
df.RAMCPU <- mutate(k8s_ram_cpu_report, RAM.AVAILABLE.GB = RAM.AVAILABLE / 1000000000) %>% mutate(RAM.ACTUAL.GB = RAM.ACTUAL / 1000000000)
CF.df <- reactive ({
if (input$ui.usage == "All"){
df.USAGE <- df.RAMCPU$USAGE
df.USAGE
}
else {
df.USAGE <- input$ui.usage
}
if (is.null(input$ui.environment)){
df.ENVIRONMENT <- df.RAMCPU$ENVIRONMENT
df.ENVIRONMENT
}
else {
df.ENVIRONMENT <- input$ui.environment
}
if (is.null(input$ui.dataCenter)){
df.GEOLOC <- df.RAMCPU$GEOLOC
df.GEOLOC
}
else {
df.GEOLOC <- input$ui.dataCenter
}
CF.df <- data %>% dplyr::filter(USAGE == df.USAGE, ENVIRONMENT == df.ENVIRONMENT, GEOLOC == df.GEOLOC)
return(CF.df)
})
ram.lg.data <- reactive({
ram.lg.data <- select(CF.df(), CLUSTER.NAME, RAM.AVAILABLE.GB, RAM.ACTUAL.GB)
ram.lg.data <- mutate(ram.lg.data, RAM.DIFFERENCE = RAM.AVAILABLE.GB - RAM.ACTUAL.GB) %>%
arrange(desc(RAM.DIFFERENCE)) %>%
head(n = 20) %>%
select(CLUSTER.NAME, RAM.AVAILABLE.GB, RAM.ACTUAL.GB)
ram.lg.data <- melt(ram.lg.data)
return(ram.lg.data)
})
CFNavbarTab.r
library(shiny)
library(dplyr)
library(ggplot2)
library(reshape2)
CFNavbarTabUI <- function(id) {
ns <- NS(id)
tagList(
fluidRow(
column(12,
column(3,
radioButtons(ns("ui.usage"), "Cluster Usage",
c("All" = "All", "Dedicated"="Dedicated", "Shared"="Shared"), selected = "All"
),
selectInput(ns("ui.environment"), "Environment", choices = c("infratest", "infradev", "nonprod", "prod"), selectize = TRUE, multiple = TRUE),
selectInput(ns("ui.dataCenter"), "Data Center", choices = c("DLLSTXCF", "ALPRGAED", "ALPSGACT", "STLSMORC"), selectize = TRUE, multiple = TRUE )
),
column(9,
plotOutput(ns("CF.plot"))
)
)
)
)
}
CFNavbarTab <- function(input, output, session, data){
data <- reactive({
data <- ram.lg.data()
})
# Plot
output$CF.plot <- renderPlot({
# Plot
CF.p <- ggplot(data(), aes(CLUSTER.NAME, value, fill = variable))
CF.p +
geom_bar(stat="identity",position="dodge") +
coord_flip() +
labs(x = "Cluster Name", y = "RAM (in GB)")
})
}
Here is some data for df.RAMCPU:
structure(list(ENVIRONMENT = structure(c(1L, 3L, 3L, 3L, 3L,
3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 2L, 3L,
3L, 3L, 3L, 3L, 3L), .Label = c("infradev", "infratest", "nonprod",
"prod"), class = "factor"), GEOLOC = structure(c(7L, 10L, 1L,
1L, 2L, 2L, 2L, 1L, 2L, 2L, 2L, 2L, 4L, 4L, 5L, 6L, 6L, 6L, 6L,
6L, 6L, 7L, 7L, 7L, 7L, 7L), .Label = c("ALPRGAED", "ALPSGACT",
"ATLDGA93", "ATLMGACX", "BOTHWAKY", "BRHMALDC", "DLLSTXCF", "FFPRGAED",
"FRFDCA60", "HYWRCA02", "KGMTNC20", "KMPRGAED", "KSCYMOAU", "SFLDMIBB",
"SNDGCA64", "STLSMORC"), class = "factor"), USAGE = structure(c(1L,
2L, 2L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L,
1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 2L), .Label = c("Dedicated",
"Shared"), class = "factor"), RAM.AVAILABLE = c(458838352, 458839084,
5547148600, 229420884, 138120456, 529571480, 658022440, 278737460,
183493584, 357147792, 80535840, 205155416, 178943204, 11552987512,
229470652, 9768304124, 20461394432, 11089427244, 167490416, 131096336,
93477940, 921215052, 639531392, 1101387288, 987033660, 1114321376
), RAM.ACTUAL = c(71694412L, 24761296L, 56935940L, 38210952L,
25184700L, 85681808L, 77821724L, 41700840L, 36413632L, 32338584L,
41430556L, 41664640L, 86492572L, 133578312L, 55139564L, 219483468L,
923218644L, 741387120L, 71859472L, 56494056L, 33996208L, 401019200L,
233304628L, 497478896L, 78335012L, 343349352L), CPU.AVAILABLE = c(112L,
112L, 560L, 56L, 38L, 104L, 120L, 60L, 36L, 56L, 28L, 42L, 88L,
1568L, 56L, 1176L, 2352L, 1176L, 44L, 32L, 28L, 156L, 136L, 216L,
204L, 272L), CPU.ACTUAL = c(0.535, 0.1497, 0.0526, 0.3811, 0.9085,
1.1026, 0.4709, 1.0248, 0.8243, 0.4044, 2.0725, 0.8144, 1.1668,
0, 0.7195, 0.2941, 2.4276, 0.4515, 1.1699, 0.2949, 0.3424, 1.8434,
2.5034, 2.606, 0.2734, 4.2449), RAM.AVAILABLE.GB = c(0.458838352,
0.458839084, 5.5471486, 0.229420884, 0.138120456, 0.52957148,
0.65802244, 0.27873746, 0.183493584, 0.357147792, 0.08053584,
0.205155416, 0.178943204, 11.552987512, 0.229470652, 9.768304124,
20.461394432, 11.089427244, 0.167490416, 0.131096336, 0.09347794,
0.921215052, 0.639531392, 1.101387288, 0.98703366, 1.114321376
), RAM.FREE.. = c(84.37, 94.6, 98.97, 83.34, 81.76, 83.82, 88.17,
85.03, 80.15, 90.94, 48.55, 79.69, 51.66, 98.84, 75.97, 97.75,
95.48, 93.31, 57.09, 56.9, 63.63, 56.46, 63.51, 54.83, 92.06,
69.18), CPU.FREE.. = c(99.52, 99.86, 99.99, 99.31, 97.6, 98.93,
99.6, 98.29, 97.71, 99.27, 92.59, 98.06, 98.67, 100, 98.71, 99.97,
99.89, 99.96, 97.34, 99.07, 98.77, 98.81, 98.15, 98.79, 99.86,
98.43), CLUSTER.NAMES = c("a", "b", "c", "d", "e", "f", "g",
"h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t",
"u", "v", "w", "x", "y", "z")), class = "data.frame", .Names = c("ENVIRONMENT",
"GEOLOC", "USAGE", "RAM.AVAILABLE", "RAM.ACTUAL", "CPU.AVAILABLE",
"CPU.ACTUAL", "RAM.AVAILABLE.GB", "RAM.FREE..", "CPU.FREE..",
"CLUSTER.NAMES"), row.names = c(NA, -26L))