Open modal on menuItem click - r

I would like to greet the user of my app with a modal once they click on a specific menuItem in the sidebar of my ShinyDashboard. Here's a simple recreation of my previous attempt:
# libraries
library(shiny)
library(shinydashboard)
## UI ##
ui <- dashboardPage(
skin = "black",
dashboardHeader(),
dashboardSidebar(
sidebarMenu(id = "sidebarmenu",
menuItem("Dashboard", tabName = "dashboard"),
menuItem("Subitems", tabName = "subitems",
menuSubItem("Upload", "upload"),
menuSubItem("Browse", "browse")
),
menuItem("Widgets", tabName = "widgets")
)
),
dashboardBody(
uiOutput('tab')
)
)
## server ##
server <- function(input, output) {
output$tab <- renderUI({
paste("The selected tab is", input$sidebarmenu)
})
observeEvent(input$sidebarmenu == "widgets", {
showModal(
modalDialog(title = "You selected Widgets", "Or did you?")
)
})
}
shinyApp(ui, server)
The goal is to open the modal only when the menuItem widgets is selected. Despite the condition input$sidebarmenu == "widgets", this does not happen. Rather, the modal is displayed any time the user switches menuItems. Why is this the case and how can I do this properly?
Thank you in advance for any input.

Add this to the observeEvent
observeEvent(input$sidebarmenu, {
req(input$sidebarmenu == "widgets")
showModal(
modalDialog(title = "You selected Widgets", "Or did you?")
)
})

Related

Hide/show menuitem in Shiny

I want to hide and show a menuItem when a user check a box. I used useShinyjs() and renderMenu() function but once the menuItem is shown, I cannot hide it again by unchecking the box.
This is what I did :
library(shiny)
library(shinydashboard)
library(shinyjs)
header <- dashboardHeader(title = "my app")
sidebar <- dashboardSidebar(
sidebarMenu(id="menu",
menuItem("Tab 1",tabName = "tab1", icon = icon("question")),
menuItemOutput("another_tab"),
menuItem("Tab 2", tabName = "tab2", icon = icon("home"))
)
)
)
body <- dashboardBody(
tabItems(
tabItem(tabName = "tab1",
useShinyjs(),
checkboxInput("somevalue", "Check me", FALSE)
)
)
)
ui <- dashboardPage(header, sidebar, body)
server <- function(input, output) {
output$another_tab <- renderMenu({
if(input$somevalue == TRUE)
menuItem("My tab", tabName = "tab3", icon = icon("cogs"))
})
}
shinyApp(ui, server)
How can we hide the menuItem again ?
Another way to do it is
output$another_tab <- renderMenu({
if(input$somevalue == TRUE) {
menuItem("My tab", tabName = "tab3", icon = icon("cogs"))
}else shinyjs::hide(selector = "a[data-value='tab3']" )
})
You can create an empty menuItem():
server <- function(input, output) {
output$another_tab <- renderMenu({
if(input$somevalue == TRUE)
menuItem("My tab", tabName = "tab3", id="tab3", icon = icon("cogs"))
else
menuItem(NULL)
})
}

Loading shiny module only when menu items is clicked

Background
Within a modular1 Shiny application, I would like to load module only when menu item on shinydashboard is clicked. If the menu item is not accessed I wouldn't like to load the module.
Basic application
app.R
# Libs
library(shiny)
library(shinydashboard)
# Source module
source("sample_module.R")
ui <- dashboardPage(
dashboardHeader(title = "Dynamic sidebar"),
dashboardSidebar(sidebarMenuOutput("menu")),
dashboardBody(tabItems(
tabItem(tabName = "tab_one", h1("Tab One")),
tabItem(tabName = "tab_two", sampleModuleUI("sampleModule"))
))
)
server <- function(input, output) {
callModule(sampleModuleServer, "sampleModule")
output$menu <- renderMenu({
sidebarMenu(
menuItem(
"Menu item 1",
icon = icon("calendar"),
tabName = "tab_one"
),
menuItem(
"Menu item 2",
icon = icon("globe"),
tabName = "tab_two"
)
)
})
}
shinyApp(ui, server)
sample_module.R
sampleModuleServer <- function(input, output, session) {
output$plot1 <- renderPlot({
plot(mtcars)
})
}
sampleModuleUI <- function(id) {
ns <- NS(id)
plotOutput(ns("plot1"))
}
Desired implementation
The desired implementation would load sample_module only when the relevant menu item is clicked. On the lines of 2:
Don't call callModule from inside observeEvent; keep it at the top level. Take the reactive expression that's returned, and use eventReactive to wrap it in the button click. And use the eventReactive from your outputs, etc.
x <- callModule(...)
y <- eventReactive(input$go, x())
output$tbl <- DT::renderDataTable(y())
Attempt
app.R (modified)
# Libs
library(shiny)
library(shinydashboard)
# Source module
source("sample_module.R")
ui <- dashboardPage(
dashboardHeader(title = "Dynamic sidebar"),
dashboardSidebar(sidebarMenuOutput("menu")),
dashboardBody(tabItems(
tabItem(tabName = "tab_one", h1("Tab One")),
tabItem(tabName = "tab_two", sampleModuleUI("sampleModule"))
))
)
server <- function(input, output) {
eventReactive(eventExpr = input$tab_two,
valueExpr = callModule(sampleModuleServer, "sampleModule")
)
output$menu <- renderMenu({
sidebarMenu(
menuItem(
"Menu item 1",
icon = icon("calendar"),
tabName = "tab_one"
),
menuItem(
"Menu item 2",
icon = icon("globe"),
tabName = "tab_two"
)
)
})
}
shinyApp(ui, server)
Problem
Application runs but the module does not load. Questions:
How to correctly call eventReactive on dashboard menu item? The tab_item does not seem to have id parameter is tabName equivalent in that context?
The linked discussion refers to refreshing one table. I'm trying to figure out example that will work with modules containing numerous interface element and elaborate server calls.
Clicking on Menu item 2 should display the content from the sample_module.R file.
1 Modularizing Shiny app code
2 Google groups: activate module with actionButton
Update
I've tried explicitly forcing module into application environment load using the following syntax:
eventReactive(eventExpr = input$tab_two,
valueExpr = callModule(sampleModuleServer, "sampleModule"),
domain = MainAppDomain
)
where
MainAppDomain <- getDefaultReactiveDomain()
Edit: Dropping Joe Cheng's top level statement:
# Libs
library(shiny)
library(shinydashboard)
# Source module
source("sample_module.R")
ui <- dashboardPage(
dashboardHeader(title = "Dynamic sidebar"),
dashboardSidebar(sidebarMenuOutput("menu")),
dashboardBody(tabItems(
tabItem(tabName = "tab_one", h1("Tab One")),
tabItem(tabName = "tab_two", sampleModuleUI("sampleModule"))
))
)
server <- function(input, output) {
observeEvent(input$tabs,{
if(input$tabs=="tab_two"){
callModule(sampleModuleServer, "sampleModule")
}
}, ignoreNULL = TRUE, ignoreInit = TRUE)
output$menu <- renderMenu({
sidebarMenu(id = "tabs",
menuItem(
"Menu item 1",
icon = icon("calendar"),
tabName = "tab_one"
),
menuItem(
"Menu item 2",
icon = icon("globe"),
tabName = "tab_two"
)
)
})
}
shinyApp(ui, server)
Furthermore, your sidebarMenu needs an id to access the selected tabs; please see the shinydashboard documentation.

R Shiny create menuItem after object is created/button clicked

I'm trying to dynamically generate a menuItem upon the creation of an object or click of a button (Ideally object). I have tried multiple methods and cannot seem to figure out a clean, working solution.
I have a lot of code so below shall include example code:
ui <- fluidPage(
dashboardPage(
dashboardHeader(title = "text"),
dashboardSidebar(
sidebarMenu(id = 'MenuTabs',
menuItem("Tab1", tabName = "tab1", selected = TRUE)
# menuItem("Tab1", tabName = "tab2")
)
),
dashboardBody(
tabItems(
tabItem("tab1",
actionButton("newplot", "New plot")),
tabItem("tab2",
plotOutput('Plot'))
)
)
)
)
server <- function(input, output, session){
output$Plot <- renderPlot({
input$newplot
cars2 <- cars + rnorm(nrow(cars))
plot(cars2)
})
}
shinyApp(ui, server)
Above I have 2 tabs, 1 with a button (shown), and another with a plot (hidden).
How can I get the hidden tab with the plot to appear upon clicking the button?
For bonus points, assuming the button instead created an object, how could I show the hidden menuItem given the creating of said object
Thanks
I've managed to solve it. Below is the code that will create a menuItem by pressing a button show.
ui <- fluidPage(
dashboardPage(
dashboardHeader(title = "text"),
dashboardSidebar(
sidebarMenu(id = 'MenuTabs',
menuItem("Tab1", tabName = "tab1", selected = TRUE),
# menuItem("Tab1", tabName = "tab2")
uiOutput('ui')
)
),
dashboardBody(
tabItems(
tabItem("tab1",
actionButton("newplot", "New plot"),
actionButton("show", "Show")),
tabItem("tab2",
plotOutput('Plot'))
)
)
)
)
server <- function(input, output, session){
output$Plot <- renderPlot({
input$newplot
# Add a little noise to the cars data
cars2 <- cars + rnorm(nrow(cars))
plot(cars2)
})
output$ui <- renderUI({
if(input$show == 0) return()
print(input$show)
sidebarMenu(id = 'MenuTabs',
menuItem("Tab1", tabName = "tab2")
)
})
}
shinyApp(ui, server)

Shinydashboard skin effect is not working after renderUI

I am trying to render shinydashboard after login page but shinydashboard skin color is not showing.
my code is as follow:
ui.r
library(shinydashboard)
library(shiny)
uiOutput("page")
Login.R
library(shinydashboard)
ui1Output <- function(id, label = "ui1") {
shinyUI(fluidPage(
mainPanel(
textInput("username","Username",placeholder ="UserName"),
passwordInput("password","Password", placeholder ="Password"),
actionButton("login", "Login")
)))
}
dashbaordpage.R
library(shinydashboard)
dashpageOutput <- dashboardPage(
dashboardHeader(title = "Basic dashboard"),
dashboardSidebar(
sidebarMenu(
menuItem("Dashboard", tabName = "dashboard", icon = icon("dashboard")),
menuItem("Widgets", tabName = "widgets", icon = icon("th"))
)
),
dashboardBody(
tabItems(
# First tab content
tabItem(tabName = "dashboard",h2("Dashbaord")),
# Second tab content
tabItem(tabName = "widgets",
h2("Widgets tab content")
)
)
)
global.R
source('login.R') #login page
source('dashboardPage.R')#dashbaordpage
server.R
library(shiny)
library(shinydashboard)
shinyServer(function(input, output,session) {
output$page <- renderUI({
ui1Output('ui1Output')
})
observeEvent(input$login,
{
if(True)
{
output$page <- renderUI(dashpageOutput)
}
else
{
Logged<-F
showModal(modalDialog(
title = "Error",
"Enter Correct Username and password"
))
}
})
})
Details: when I going dashboard is showing but not with default skin color or any other skin color. I have tried skin='red' like wise option.
Image for reference how actually showing after login.
Please help me.
Thanks in advance.

Navigate to particular sidebar menu item in ShinyDashboard?

(cross post from shiny google groups, https://groups.google.com/forum/#!topic/shiny-discuss/CvoABQQoZeE)
How can one navigate to a particular sidebar menu item in ShinyDashboard?
sidebarMenu(
menuItem("Menu Item 1")
menuItem("Menu Item 2")
)
i.e. how can I put a button on the "Menu Item 1" page that will link to "Menu Item 2"?
To navigate between tabs I am using the updateTabsetPanel function:
observeEvent(input$go,{
updateTabsetPanel(session, "tabset1", selected = "Step 2")
})
I believe I should be able to use a similar function to navigate to a sidebar menu, but I am not sure what that is.
Any pointers greatly appreciated
Thanks
Iain
Is this what you are looking for? note that the example is taken from Change the selected tab on the client
library(shiny)
library(shinydashboard)
ui <- dashboardPage(
dashboardHeader(title = "Simple tabs"),
dashboardSidebar(
sidebarMenu(id = "tabs",
menuItem("Menu Item 1", tabName = "one", icon = icon("dashboard")),
menuItem("Menu Item 1", tabName = "two", icon = icon("th"))
)
),
dashboardBody(
tabItems(
tabItem(tabName = "one",h2("Dashboard tab content"),actionButton('switchtab', 'Switch tab')),
tabItem(tabName = "two",h2("Widgets tab content"))
)
)
)
server <- function(input, output, session) {
observeEvent(input$switchtab, {
newtab <- switch(input$tabs, "one" = "two","two" = "one")
updateTabItems(session, "tabs", newtab)
})
}
shinyApp(ui, server)

Resources