Rshiny modal popup when good tab selected with navbarPage function - r

I have a modular Rshiny application in which I want to display a dataset selection popup (modal) ONLY when the user is on the "TAB 1" tab.
Ideally, I would like this popup to be displayed only once on the first click on the right tab.
I really don't know how to get the input on which tab is active and then, create a counter to display popup only if counter == 1....
Here is my code :
1st module :
library(shiny)
library(shinyjs)
library(shinyWidgets)
#_________________________________________________________________
# MODULE 1 ----
#_________________________________________________________________
module1_ui <- function(id) {
ns <- NS(id)
tabPanel(
title = "Home",
shiny::tags$p(
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
)
)
}
module1_server <- function(id, r_global) {
moduleServer(id, function(input, output, session) {
})
}
2nd module :
#_________________________________________________________________
# MODULE 2 ----
#_________________________________________________________________
module2_ui <- function(id) {
ns <- NS(id)
tabPanel(
title = "Tab 1",
useShinyjs(),
actionLink(
inputId = ns("display_modal"),
label = "S\u00e9lectionner les donn\u00e9es",
style = "position: relative; left:90%"
),
tableOutput(outputId = ns("myTable"))
)
}
module2_server <- function(id, r_global) {
moduleServer(id, function(input, output, session) {
ns <- session$ns
#_________________________________________________________________
# MODAL DEFINITION ----
#_________________________________________________________________
dataModal <- function(failed = FALSE) {
modalDialog(
shiny::tags$h3("Choose dataset : "),
panel(
shinyWidgets::pickerInput(
inputId = ns("dataset_select"),
label = "Dataset :",
choices = c("dt1" = "dt1",
"dt2" = "dt2"),
multiple = FALSE,
options = list(`actions-box` = TRUE)
)
),
footer = tagList(
modalButton(label = "Cancel"),
actionButton(inputId = ns("ok"), label = "OK")
)
)
}
#_________________________________________________________________
# SHOW MODAL ----
#_________________________________________________________________
showModal(dataModal())
#_________________________________________________________________
# ACTION WHEN CLICKING ON OK MODAL ----
#_________________________________________________________________
observeEvent(input$ok, {
removeModal()
output$myTable = renderTable({
if(input$dataset_select == "dt1"){
iris
}else{
mtcars
}
})
})
#________________________________________________________________
# ACTION WHEN CLICKING ON LINK TO DISPLAY MODAL ----
#________________________________________________________________
observeEvent(input$display_modal, {
showModal(dataModal())
})
})
}
UI et SERVER:
#________________________________________________________________
# MAIN UI ----
#________________________________________________________________
app_ui <- function(request) {
tagList(
navbarPage(id = "main_menu", "My app",
module1_ui("mod1"),
module2_ui("mod2")
)
)
}
#________________________________________________________________
# MAIN SERVER ----
#________________________________________________________________
app_server <- function(input, output, session) {
r_global <- reactiveValues(data = NULL)
module1_server(id = "mod1", r_global = r_global)
module2_server(id = "mod2", r_global = r_global)
}
shinyApp(ui = app_ui, server = app_server)

One option would be to use a reactive in the main server to store the selected tab and pass it to the module 2 server via an additional argument. Inside the module 2 server you could use an observeEvent and check that you are on Tab 1. Additionally I implemented a counter as a reactiveVal such that the modal pops up only when listing Tab 1 the first time.
Code below includes only the module 2 server and the main server:
module2_server <- function(id, r_global, tab) {
moduleServer(id, function(input, output, session) {
ns <- session$ns
counter <- reactiveVal(1)
# _________________________________________________________________
# MODAL DEFINITION ----
# _________________________________________________________________
dataModal <- function(failed = FALSE) {
modalDialog(
shiny::tags$h3("Choose dataset : "),
panel(
shinyWidgets::pickerInput(
inputId = ns("dataset_select"),
label = "Dataset :",
choices = c(
"dt1" = "dt1",
"dt2" = "dt2"
),
multiple = FALSE,
options = list(`actions-box` = TRUE)
)
),
footer = tagList(
modalButton(label = "Cancel"),
actionButton(inputId = ns("ok"), label = "OK")
)
)
}
# _________________________________________________________________
# SHOW MODAL ----
# _________________________________________________________________
observeEvent(tab(), {
if (tab() == "Tab 1") {
if (counter() == 1) {
showModal(dataModal())
}
counter(counter() + 1)
}
})
# _________________________________________________________________
# ACTION WHEN CLICKING ON OK MODAL ----
# _________________________________________________________________
observeEvent(input$ok, {
removeModal()
output$myTable <- renderTable({
if (input$dataset_select == "dt1") {
iris
} else {
mtcars
}
})
})
# ________________________________________________________________
# ACTION WHEN CLICKING ON LINK TO DISPLAY MODAL ----
# ________________________________________________________________
observeEvent(input$display_modal, {
showModal(dataModal())
})
})
}
app_server <- function(input, output, session) {
r_global <- reactiveValues(data = NULL)
selected_tab <- reactive({
input$main_menu
})
module1_server(id = "mod1", r_global = r_global)
module2_server(id = "mod2", r_global = r_global, tab = selected_tab)
}

Related

How do you have different server execution based on selected tabItem() in shiny?

Background
I am using {brochure} and {golem} to build a shiny app. I have one outer module grid that consists of inner modules subGrid2 which displays the same module UI on two tabs.
GOAL
have a module subGrid2 that can be used for repeating graph
visualizations on multiple tabs.
in the REPREX --> fake graph generated from {shinipsum} to
be displayed on the "Home" tab + "Portfolio" tab
use observeEvent to look at the slected tab and generate server response respectivley
Problem
The observeEvent reactive expr. fails to recognize when the corresponding tab is selected to generate the correct server response.
-using the reprex below replicates my issue-
TL/DR
Why wont the observeEvent reactive generate the correct server response per the selected tab?
REPREX
uncomment observeEvent to see error
#22.2.22
library(brochure)
library(shiny)
library(shinipsum)
library(shinydashboard)
library(shinydashboardPlus)
mod_subGrid2_ui <- function(id) {
ns <- NS(id)
tagList(
plotOutput(ns("plot"))
)
}
mod_subGrid2_server <- function(id) {
moduleServer(id, function(input, output, session) {
ns <- session$ns
output$plot <- renderPlot({
shinipsum::random_ggplot()
})
})
}
#Setup dashboard
mod_Grid_ui <- function(id) {
ns <- NS(id)
shinydashboardPlus::dashboardPage(
skin = "midnight",
header = dashboardHeader(title = "test"),
sidebar = dashboardSidebar(
shinydashboard::sidebarMenu(
# Setting id makes input$tabs give the tabName of currently-selected tab
id = "tabs",
menuItem("Home", tabName = "home", icon = icon("tachometer-alt")),
menuItem("Portfolio", tabName = "portfolio", icon = icon("chart-line"), badgeLabel = "new",
badgeColor = "green")
)
),
body = shinydashboard::dashboardBody(
# Enable shinyjs
shinyjs::useShinyjs(),
shinydashboard::tabItems(
shinydashboard::tabItem("home",
shiny::tagList(
div(p("Content for 1st tab goes here -- GRID MODULE")),
mod_subGrid2_ui(ns("subGrid2_ui_1"))
)
),
shinydashboard::tabItem("portfolio",
shiny::tagList(
div(p("Content for 2nd goes here -- GRID MODULE (2x)")),
titlePanel(title = "The same module UI goes here"),
mod_subGrid2_ui(ns("subGrid2_ui_2"))
)
)
)
)
)
}
mod_Grid_server <- function(id) {
moduleServer(id, function(input, output, session) {
ns <- session$ns
mod_subGrid2_server("subGrid2_ui_1")
mod_subGrid2_server("subGrid2_ui_2")
## uncomment to try
# observeEvent(input$tabs,{
# if(input$tabs == "home"){
# # <subGrid> server fragment
# mod_subGrid2_server("subGrid2_ui_1")
# } else if(input$tabs == "portfolio"){
# mod_subGrid2_server("subGrid2_ui_1")
# }
# }, ignoreNULL = TRUE, ignoreInit = TRUE)
})
}
brochureApp(
page(
href = "/",
ui = tagList(
mod_Grid_ui("grid_1")
),
server = function(input, output, session) {
mod_Grid_server("grid_1")
}
),
wrapped = shiny::tagList
)
When using a module nested inside another module, you need to ns() the id of the nested UI function.
So here, mod_subGrid2_ui(ns("subGrid2_ui_1")).
Here is a minimal reprex:
mod_subGrid2_ui <- function(id) {
ns <- NS(id)
tagList(
plotOutput(ns("plot"))
)
}
mod_subGrid2_server <- function(id) {
moduleServer(id, function(input, output, session) {
ns <- session$ns
output$plot <- renderPlot({
shinipsum::random_ggplot()
})
})
}
mod_Grid_ui <- function(id) {
ns <- NS(id)
tagList(
mod_subGrid2_ui(ns("subGrid2_ui_1"))
)
}
mod_Grid_server <- function(id) {
moduleServer(id, function(input, output, session) {
ns <- session$ns
mod_subGrid2_server("subGrid2_ui_1")
})
}
brochureApp(
page(
href = "/",
ui = tagList(
mod_Grid_ui("grid_1")
),
server = function(input, output, session) {
mod_Grid_server("grid_1")
}
)
)

Shiny modules: switch tabs from within modules that have different namespaces

I have a shiny app with multiple tabs, and I would like to have action buttons within the tabs that allow the user to switch tabs. I previously asked this question: R Shiny: Change tabs from within a module
and got an answer that helped, but didn't completely solve my problem.
When I use the same id (tab.1) to call modtab1 and modtab2, it allows me to switch tabs, but it doesn't distinguish between the two input$userids; when I use different id's it distinguishes between the two input$userids but doesn't allow me to switch tabs.
library(shiny)
modtab1_ui <- function(id) {
ns <- NS(id)
tabPanel(title = 'Tab 1',
value = NS(id, 'tab.1'),
h4('This is the first tab'),
actionButton(NS(id, 'nexttab'), 'Next Tab'),
textInput(NS(id, 'userid'), 'User ID'),
textOutput(outputId = NS(id, 'id'))
) # tabPanel
}
modtab1_server <- function(id) {
moduleServer(id,
function(input, output, session) {
observeEvent(input$nexttab, {
print(paste('switching to tab 2', input$userid))
updateTabsetPanel(session = session, inputId = 'tabs',
# selected = NS('tab2', 'tab.2')
# selected = 'tab.2'
selected = ns('tab.2')
)
})
output$id <- renderText(input$userid)
})
}
modtab2_ui <- function(id) {
ns <- NS(id)
tabPanel(title = 'Tab 2',
value = NS(id, 'tab.2'),
h4('This is the second tab'),
actionButton(NS(id, 'firsttab'), 'First Tab'),
textInput(NS(id, 'userid'), 'User ID'),
textOutput(outputId = NS(id, 'useridout'))
) # tabPanel
}
modtab2_server <- function(id) {
moduleServer(id,
function(input, output, session) {
observeEvent(input$firsttab, {
print(paste('switching to tab 1', input$userid))
updateTabsetPanel(session = session, inputId = 'tabs',
# selected = NS('tab1', 'tab.1')
# selected = 'tab.1'
selected = ns('tab.1')
)
})
output$id <- renderText(input$userid)
})
}
ui <- fluidPage(
tabsetPanel(
'tabs',
modtab1_ui('tab1'),
modtab2_ui('tab2')
)
)
server <- function(input, output, session) {
modtab1_server('tab1')
modtab2_server('tab2')
}
shinyApp(ui = ui, server = server)
Here's a MWE that, I think, gives you what you want.
library(shiny)
modtab1_ui <- function(id) {
ns <- NS(id)
tabPanel(
title = 'Tab 1',
value = ns('tab'),
h4('This is the first tab'),
actionButton(ns('nexttab'), 'Next Tab')
) # tabPanel
}
modtab1_server <- function(id) {
moduleServer(id,
function(input, output, session) {
retVal <- reactiveValues(count=0)
observeEvent(input$nexttab, retVal$count <- retVal$count + 1)
return(reactive(retVal$count))
})
}
modtab2_ui <- function(id) {
ns <- NS(id)
tabPanel(
title = 'Tab 2',
value = ns('tab'),
h4('This is the second tab'),
actionButton(ns('firsttab'), 'First Tab')
) # tabPanel
}
modtab2_server <- function(id) {
moduleServer(id,
function(input, output, session) {
retVal <- reactiveValues(count=0)
observeEvent(input$firsttab, retVal$count <- retVal$count + 1)
return(reactive(retVal$count))
})
}
ui <- fluidPage(
tabsetPanel(
id='tabs',
modtab1_ui('tab1'),
modtab2_ui('tab2')
)
)
server <- function(input, output, session) {
tab1val <- modtab1_server('tab1')
tab2val <- modtab2_server('tab2')
observeEvent(tab1val(), {
updateTabsetPanel(session, 'tabs', selected = 'tab2-tab')
})
observeEvent(tab2val(), {
updateTabsetPanel(session, 'tabs', selected = 'tab1-tab')
})
}
shinyApp(ui = ui, server = server)
Note the changes to your syntax, particularly regarding the use of ns and NS and the arguments passed to the functions.
Also, note the use of return values from the module server functions, and how they are accessed within the main server function.
Building off of Limey's response. You can streamline to one module by additional formals to the UI module.
library(shiny)
modTabUi <- function(id, panelTitle = 'Tab 1', headding = 'This is the first tab', buttonLabel = 'Next Tab') {
ns <- NS(id)
tabPanel(
title = panelTitle,
value = ns('tab'),
h4(headding),
actionButton(ns('nexttab'), buttonLabel)
)
}
modTabServer <- function(id) {
moduleServer(id,
function(input, output, session) {
retVal <- reactiveValues(count = 0)
observeEvent(input$nexttab, retVal$count <- retVal$count + 1)
return(reactive(retVal$count))
})
}
ui <- fluidPage(
tabsetPanel(
id='tabs',
modTabUi('tab1', panelTitle = 'Tab 1', headding = 'This is the first tab', buttonLabel = 'Next Tab'),
modTabUi('tab2', panelTitle = 'Tab 2', headding = 'This is the second tab', buttonLabel = 'Back to First Tab')
)
)
server <- function(input, output, session) {
tab1val <- modTabServer('tab1')
tab2val <- modTabServer('tab2')
observeEvent(tab1val(), {
updateTabsetPanel(session, 'tabs', selected = 'tab2-tab')
})
observeEvent(tab2val(), {
updateTabsetPanel(session, 'tabs', selected = 'tab1-tab')
})
}
shinyApp(ui = ui, server = server)

How to dynamically update dropdown within a modulized shinyalert for each iteration of a for loop, when using html = TRUE?

I'm creating a shiny module, where I wish to display some pop-up messages to the user via shinyalerts and include dropdown menus via htlm = TRUE and shinyWidgets::pickerInput. For each shinyalert the options should be different and the alerts should appear right after each other when the user has selected the relevant option.
However, when running the shinyalerts within a for loop, only the first alert shows the drop-down, the following does not. Please have a look at the example below and screenshots. Any ideas what I'm doing wrong?
Module UI:
mod_match_columns_ui <- function(id){
ns <- NS(id)
tagList(
shinyalert::useShinyalert(),
actionButton(ns("run"), label = "Start!")
)
}
Module server:
mod_match_columns_server <- function(input, output, session){
ns <- session$ns
options <- list(c("option_1","option_2"),
c("option_3","option_4"))
observeEvent(input$run, {
for(col in 1:2){
nms <- options[[i]]
output[[paste0("dropdown",col)]] <- renderUI({
shinyWidgets::pickerInput(
inputId = ns(paste0("options",col)),
label = "Options listed below",
choices = nms,
selected = "",
multiple = FALSE,
options = shinyWidgets::pickerOptions(size = 15)
)
})
shinyalert::shinyalert(
title = "Pick an option!",
html = TRUE,
text = tagList(
uiOutput(ns(paste0("dropdown", col)))
),
inputId = ns(paste0("modal", col))
)
}
})
}
Run module:
library(shiny)
ui <- fluidPage(
mod_match_columns_ui("match_columns_ui_1")
)
server <- function(input, output, session) {
callModule(mod_match_columns_server, "match_columns_ui_1")
}
shinyApp(ui = ui, server = server)
First iteration:
Second iteration:
Why is the dropdown not shown in the second iteration?? Thanks
Try this
library(shiny)
library(shinyalert)
mod_match_columns_ui <- function(id){
ns <- NS(id)
tagList(
shinyalert::useShinyalert(),
actionButton(ns("run"), label = "Start!")
)
}
mod_match_columns_server <- function(id) {
moduleServer(id,
function(input, output, session) {
ns <- session$ns
options <- list(c("option_1","option_2"),
c("option_3","option_4"))
lapply(1:2, function(col){
output[[paste0("dropdown",col)]] <- renderUI({
shinyWidgets::pickerInput(
inputId = ns(paste0("options",col)),
label = paste("Options",col,"listed below"),
choices = options[[col]],
selected = "",
multiple = FALSE,
options = shinyWidgets::pickerOptions(size = 15)
)
})
})
observeEvent(input$run, {
shinyalert::shinyalert(
title = "Pick an option!",
html = TRUE,
text = tagList(
lapply(1:2, function(i){uiOutput(ns(paste0("dropdown",i)))})
)
# callbackR = function(x) { message("Hello ", x) },
# inputId = ns(paste0("modal"))
)
})
observe({
print(input$options1)
print(input$options2)
print(input$shinyalert)
})
})
}
ui <- fluidPage(
tagList(
mod_match_columns_ui("match_columns_ui_1")
)
)
server <- function(input, output, session) {
mod_match_columns_server("match_columns_ui_1")
}
shinyApp(ui = ui, server = server)

How to update progress bar across over several modules and app in shiny?

Hi I´m very new to R programming.
Currently I´m working on a dashboard to create some data and display it.
This project got quite big quite quickly so I'm trying to modularize the dashboard.
That caused me the some problems. One being this Multiple tabItems in one shiny module.
Another being that I want / need to provide a progress bar for the user since the data processing takes up quite some time.
This processing of data is now divided in multiple modules like in the example below.
But the bar won't update itselfe further than the first module.
My guess is that the id's aren't matching and therefor the following updates aren't found.
I ain´t have any idea to "isolate" the id of updateProgressBar() and pass it across the modules.
Thanks so much for your help!
library(shiny)
library(shinydashboard)
library(shinydashboardPlus)
library(shinyWidgets)
#module_1
module_1_ui <- function(id){
ns <- NS(id)
tagList(
boxPlus(
title = "some title",
textOutput(ns("some_output"))
)
)
}
module_1_server <- function(id,see){
moduleServer(
id,
function(input, output, session){
ns <- session$ns
observe({
progressSweetAlert(
id = ns("progress"),
session = session,
value = 1,
total = 4,
)
Sys.sleep(1) #dummy for some functions that take some time to process
updateProgressBar(
id = ns("progress"),
session = session,
value = 2,
total = 4
)
})
output$some_output <- renderText({
see
})
}
)
}
#module_1
module_2_ui <- function(id){
ns <- NS(id)
tagList(
boxPlus(
title = "some title",
textOutput(ns("some_output"))
)
)
}
module_2_server <- function(id,see){
moduleServer(
id,
function(input, output, session){
ns <- session$ns
observe({
updateProgressBar(
session = session,
id = ns("progress"),
value = 3,
total = 4
)
Sys.sleep(4) #dummy for some functions that take some time to process
updateProgressBar(
session = session,
id = ns("progress"),
value = 4,
total = 4
)
Sys.sleep(2)
closeSweetAlert(session = session)
})
output$some_output <- renderText({
see
})
}
)
}
#app
ui <- dashboardPagePlus(
header = dashboardHeaderPlus(
title = "dummy app"
),
sidebar = dashboardSidebar(
sidebarMenu(
menuItem(
text = "home",
tabName = "home"
),
menuItem(
text = "module_1",
tabName = "tab_1"
),
menuItem(
text = "module_2",
tabName = "tab_2"
),
menuItem(
text = "some other tabItems",
tabName = "some_other_tabItems"
)
)
),
body = dashboardBody(
tabItems(
tabItem(
tabName = "home",
box(
title = "home of the app",
width = "auto"
)
),
tabItem(
tabName = "tab_1",
module_1_ui(
id = "module_1"
)
),
tabItem(
tabName = "tab_2",
module_2_ui(
id = "module_2"
)
),
tabItem(
tabName = "some_other_tabItems",
box(
title = "some other content"
)
)
)
)
)
server <- function(input, output){
module_1_server(
id = "module_1",
see = "something happens here"
)
module_2_server(
id = "module_2",
see = "something happens here as well"
)
}
shinyApp(ui,server)
I would push the progress update to the main app and let the modules simply notify the main app that it should update the progress bar. As it was not clear from your code how (in which sequence) the modules do their job and how the first module is strated, I made some assumptions:
The code ist started with a press on the Start button.
The first module does only one update. Once it is finished it notifies the second module to start.
The second module starts once the first module is finished and does 3 steps.
library(shiny)
library(shinyWidgets)
library(shinydashboard)
library(shinydashboardPlus)
m1_ui <- function(id) {
ns <- NS(id)
boxPlus(
title = "Module 1",
textOutput(ns("text_output"))
)
}
m1_server <- function(id, content, start) {
moduleServer(id,
function(input, output, session) {
trigger_update <- reactiveVal(0)
finished <- reactiveVal(FALSE)
observeEvent(start(), {
Sys.sleep(1)
trigger_update(trigger_update() + 1)
finished(rnorm(1))
}, ignoreInit = TRUE)
output$text_output <- renderText(content)
list(trigger_update = trigger_update,
finished = finished)
})
}
m2_ui <- function(id) {
ns <- NS(id)
boxPlus(
title = "Module 2",
textOutput(ns("text_output"))
)
}
m2_server <- function(id, content, start) {
moduleServer(id,
function(input, output, session) {
trigger_update <- reactiveVal(0)
trigger_next_step <- reactiveVal(0)
finished <- reactiveVal(FALSE)
observeEvent(start(), {
Sys.sleep(1)
trigger_update(trigger_update() + 1)
trigger_next_step(1)
}, ignoreInit = TRUE)
observeEvent(trigger_next_step(), {
Sys.sleep(1)
trigger_update(trigger_update() + 1)
if (trigger_next_step() <= 2) {
trigger_next_step(trigger_next_step() + 1)
} else {
finished(TRUE)
}
}, ignoreInit = TRUE
)
output$text_output <- renderText(content)
list(trigger_update = trigger_update,
finished = finished)
})
}
ui <- dashboardPagePlus(
dashboardHeaderPlus(
title = "dummy app"
),
dashboardSidebar(),
dashboardBody(fluidRow(actionButton("start", "Start")),
fluidRow(m1_ui("m1"), m2_ui("m2")))
)
server <- function(input, output, session) {
m1_handler <- m1_server("m1", "text 1", reactive(input$start))
m2_handler <- m2_server("m2", "text 2", m1_handler$finished)
current_status <- reactiveVal(0)
observeEvent({
m1_handler$trigger_update()
m2_handler$trigger_update()
}, {
current_status(current_status() + 1)
print(paste("Update", current_status()))
},
ignoreInit = TRUE
)
observeEvent(input$start, {
progressSweetAlert(
id = "progress",
session = session,
value = 0,
total = 4,
)
}
)
observe({
req(current_status() > 0)
if (current_status() < 5) {
updateProgressBar(session, "progress", value = current_status(), total = 4)
} else {
current_status(0)
closeSweetAlert(session)
}
})
}
shinyApp(ui, server)

Using data from one shiny module to another shiny module

I am trying to use a value from one shiny module and pass it to a second shiny module to print it. So when user select orange from first dropdown it show print you have selected orange. But as of now it prints you have selected ATC which is nothing but the id I am passing . Below is the code I am using.Thank you.
library(shiny)
library(shinydashboard)
library(shinyWidgets)
dropDownUI <- function(id, div_width = "col-xs-12 col-md-8") {
ns <- NS(id)
div(column(3, uiOutput(ns("class_level"))),
column(3,uiOutput(ns("selected_product_ui"))
))
}
chartTableBoxUI <- function(id, div_width = "col-xs-12 col-md-8") {
ns <- NS(id)
div(tabBox(width = 12, title = id,
tabPanel(icon("bar-chart"),
textOutput(ns("selected_var")))
)
)
}
chartTableBox <- function(input, output, session, data,ImProxy) {
output$selected_var <- renderText({
ns <- session$ns
paste("You have selected",ns(ImProxy$selected_class))
})
}
dropDown <- function(input, output, session) {
ns <- session$ns
observe({output$class_level <- renderUI({
selectInput(
ns("selected_class"),
label = h4("Classification Level"),
choices = list(
"apple " = "apple",
"orange " = "orange"),
selected = "orange"
)})
})
a<-reactive({input$selected_class})
output$selected_product_ui <- renderUI({
req(input$selected_class)
Sys.sleep(0.2)
ns <- session$ns
if (input$selected_class == "apple") {
my_choices <- c("foo","zoo","boo")
} else if (input$selected_class == "orange") {
my_choices <- c("22","33","44")
} else {
my_choices <- c("aa","bb","cc")
}
selectInput(inputId = ns("selected_product"),
label = h4("Product Family"),
choices = my_choices)
})
}
sidebar <- dashboardSidebar(sidebarMenu(
menuItem("aaa",tabName = "aaa"),
menuItem("bbb", tabName = "bbb"),
menuItem("ccc", tabName = "ccc")
))
body <- ## Body content
dashboardBody(tabItems(
tabItem(tabName = "aaa",
fluidRow(dropDownUI(id = "dropdown"),
fluidRow(chartTableBoxUI(id = "ATC"))
)
)))
# Put them together into a dashboardPage
ui <- dashboardPage(
dashboardHeader(title = "Loyalty Monthly Scorecard"),
sidebar,
body
)
server = {
shinyServer(function(input, output, session) {
callModule(dropDown, id = "dropdown")
callModule(chartTableBox, id = "ATC", data = MyData)
})
}
shinyApp(ui = ui, server = server)
I tried the solution from this question Passing data within Shiny Modules from Module 1 to Module 2 using reactive values and observer event aargument "ImProxy" is missing, with no default
There are two issues with your code:
ImProxy is a user defined variable. You have not defined it, nor have you passed it as an argument.
You are using the id as the title of your tabBox.
Both are corrected below.
library(shiny)
library(shinydashboard)
library(shinyWidgets)
dropDownUI <- function(id, div_width = "col-xs-12 col-md-8") {
ns <- NS(id)
div(column(3,uiOutput(ns("class_level"))),
column(3,uiOutput(ns("selected_product_ui"))
))
}
chartTableBoxUI <- function(id, div_width = "col-xs-12 col-md-8") {
ns <- NS(id)
div(tabBox(width = 12, title = textOutput(ns("title_var")), ## fixing issue 2
tabPanel(icon("bar-chart"),
textOutput(ns("selected_var")))
)
)
}
chartTableBox <- function(input, output, session, data,a) { ## fixing issue 1
output$selected_var <- renderText({
paste("You have selected",a())
})
output$title_var <- renderText({ a() }) ## fixing issue 2
}
dropDown <- function(input, output, session) {
ns <- session$ns
observe({output$class_level <- renderUI({
selectInput(
ns("selected_class"),
label = h4("Classification Level"),
choices = list(
"apple " = "apple",
"orange " = "orange"),
selected = "orange"
)})
})
a<-reactive({input$selected_class})
output$selected_product_ui <- renderUI({
req(input$selected_class)
Sys.sleep(0.2)
ns <- session$ns
if (input$selected_class == "apple") {
my_choices <- c("foo","zoo","boo")
} else if (input$selected_class == "orange") {
my_choices <- c("22","33","44")
} else {
my_choices <- c("aa","bb","cc")
}
selectInput(inputId = ns("selected_product"),
label = h4("Product Family"),
choices = my_choices)
})
return(a) ## fixing issue 1
}
# Put them together into a dashboardPage
ui = dashboardPage(
dashboardHeader(title = "Loyalty Monthly Scorecard"),
dashboardSidebar(sidebarMenu(
menuItem("aaa",tabName = "aaa")
)),
dashboardBody(tabItems(
tabItem(tabName = "aaa",
fluidRow(dropDownUI(id = "dropdown"),
chartTableBoxUI(id = "ATC") # this text
)
)))
)
server = {
shinyServer(function(input, output, session) {
a = callModule(dropDown, id = "dropdown")
callModule(chartTableBox, id = "ATC", data = MyData, a = a)
})
}
shinyApp(ui = ui, server = server)

Resources