Navigate through tabItems using actionButton() - r

I am using the actionButton() to move from the 1st tabItem() to the 2nd but while it seems to work I remain on the first tabItem().
## app.R ##
library(shiny)
library(shinydashboard)
ui <- dashboardPage(
dashboardHeader(
),
dashboardSidebar(
collapsed = TRUE,
sidebarMenu(
id="inTabset",
menuItem("Workspace", tabName = "workspace", icon = icon("upload")),
menuItemOutput("tab2")
)
),
dashboardBody(
tabItems(
# First tab content
tabItem(tabName = "workspace",
fluidRow(
textInput("name", "", value = "Process model", placeholder = NULL),
actionButton("nextt","Next", icon("paper-plane")
)
)
)
),
tabItem(
tabName = "Process model",
)
)
)
server <- function(input, output,session) {
output$tab2 <- renderMenu({
menuItem(text = input$name, tabName = "Process model", icon = icon("diagram-project"))
})
observeEvent(input$nextt, {
updateTabItems(session, "inTabset", selected = "Process model")
})
output$tabtitle <- renderText({
if (input$name == "") {
"Process model"
} else {
paste(input$name)
}
})
observeEvent(input$nextt, {
updateTabItems(session, "inTabset", selected = "Process model")
})
}
shinyApp(ui, server)

While the name of the tab may have spaces, its value should not. This should now work i.e. Process_model:
## app.R ##
library(shiny)
library(shinydashboard)
ui <- dashboardPage(
dashboardHeader(
),
dashboardSidebar(
collapsed = TRUE,
sidebarMenu(
id="inTabset",
menuItem("Workspace", tabName = "workspace", icon = icon("upload")),
menuItemOutput("tab2")
)
),
dashboardBody(
tabItems(
# First tab content
tabItem(tabName = "workspace",
fluidRow(
textInput("name", "", value = "Process model", placeholder = NULL),
actionButton("nextt","Next", icon("paper-plane")
)
)
)
,
tabItem(
tabName = "Process_model",
))
)
)
server <- function(input, output,session) {
output$tab2 <- renderMenu({
menuItem(text = input$name, tabName = "Process_model", icon = icon("diagram-project"))
})
observeEvent(input$nextt, {
updateTabItems(session, "inTabset", selected = "Process_model")
})
output$tabtitle <- renderText({
if (input$name == "") {
"Process model"
} else {
paste(input$name)
}
})
observeEvent(input$nextt, {
updateTabItems(session, "inTabset", selected = "Process_model")
})
}
shinyApp(ui, server)

Related

Move from one menuItem to another usung actionButton() when the name of it can be changed in a shiny dashboard

I have the shiny app below in which I would like to set the name of the second menuItem() by typing in the textInput() of the first menuItem(). And then move to it by clicking an actionButton(). Also why the textOutput() I use is dispalyed under the icon and not next it like the first one?
## app.R ##
library(shiny)
library(shinydashboard)
ui <- dashboardPage(
dashboardHeader(
),
dashboardSidebar(
collapsed = TRUE,
sidebarMenu(
id="inTabset",
menuItem("Workspace", tabName = "workspace", icon = icon("upload")),
menuItemOutput("tab2")
)
),
dashboardBody(
tabItems(
# First tab content
tabItem(tabName = "workspace",
fluidRow(
textInput("name", "", value = "Process model", placeholder = NULL),
actionButton("nextt","Next", icon("paper-plane")
)
)
)
),
tabItem(
tabName = "Process model",
)
)
)
server <- function(input, output,session) {
output$tab2 <- renderMenu({
menuItem(text = input$name, tabName = "Process model", icon = icon("diagram-project"))
})
observeEvent(input$nextt, {
updateTabItems(session, "inTabset", selected = "Process model")
})
output$tabtitle <- renderText({
if (input$name == "") {
"Process model"
} else {
paste(input$name)
}
})
observeEvent(input$nextt, {
updateTabItems(session, "inTabset", selected = "Process model")
})
}
shinyApp(ui, server)
To dynamically create and name a menuItem you could use renderMenu and menuItemOutput.
library(shinydashboard)
library(shiny)
ui <- dashboardPage(
dashboardHeader(title = "Basic dashboard"),
dashboardSidebar(
sidebarMenu(
id = "inTabset",
menuItem("Dashboard", tabName = "dashboard", icon = icon("dashboard")),
menuItemOutput("tab2")
)
),
dashboardBody(
tabItems(
tabItem(
tabName = "dashboard",
textInput("name", "Create a name for your process", value = "", placeholder = NULL),
actionButton("nextt", "Next")
),
tabItem(
tabName = "widgets"
)
)
)
)
server <- function(input, output, session) {
observeEvent(input$nextt, {
updateTabItems(session, "inTabset", selected = "widgets")
})
output$tab2 <- renderMenu({
menuItem(text = input$name, tabName = "widgets", icon = icon("th"))
})
output$tabtitle <- renderText({
if (input$name == "") {
"Name of process"
} else {
paste(input$name)
}
})
observeEvent(input$nextt, {
updateTabItems(session, "inTabset", selected = "widgets")
})
}
shinyApp(ui, server)

Reset in Shiny applications

I am trying to clear what ever is written in the text area but looks like it not working. Based on the below applications, when the user clicks on "click" button, the contents (if written) should get cleared. But it is not. Can anyone help me here please........................................
data(mtcars)
library(shiny)
library(shinydashboard)
library(dplyr)
library(DT)
library(shinyjs)
ui <- dashboardPage(
dashboardHeader(title = "Dynamic sidebar"),
dashboardSidebar(sidebarMenu(id = "menu", sidebarMenuOutput("menu"))),
dashboardBody(tabItems
(
tabItem
(tabName = "plots", h2("Dashboard plots"),
fluidRow(column(width = 12, class = "well",
h4("Boxplot"),
plotOutput("bxp")))
),
tabItem(tabName = "dashboard", h2("Dashboard tab content"),
dataTableOutput(outputId = "subdt"),textAreaInput("sd","label1"),textAreaInput("sd1","label2") ,
actionButton("idff","click"))
)
)
)
server <- function(input, output, session) {
output$menu <- renderMenu({
sidebarMenu(
# menuItem("Plots Menu", tabName = "plots", icon = icon("line-chart")),
menuItem("Table Menu", icon = icon("info"),
menuSubItem(
"Dashboard", tabName = "dashboard", icon = icon("calendar")
),
selectInput(
inputId = "mcm", label = "Some label", multiple = TRUE,
choices = unique(mtcars$cyl), selected = unique(mtcars$cyl)
)
)
)
})
observe({
print(input$menu)
})
datsub <- reactive({
mtcars %>%
filter_at(vars("cyl"), all_vars(. %in% input$mcm))
})
output$subdt <- renderDataTable({
datatable(datsub(),selection = if(input$menu == "dashboard"){'single'} else {'none'})
# print(datatable.selection())
})
# datatable(datsub(),selection = if(input$menu == "dashboard"){'single'} else {'none'})
output$bxp <- renderPlot({
hist(rnorm(100))
})
observeEvent(input$idff,{
print("cjec")
shinyjs::reset('sd')
shinyjs::reset('sd1')
})
}
shinyApp(ui, server)
I'd suggest to update the textAreaInput as suggested in the comments. Update the event handler as follows:
observeEvent(input$idff, {
updateTextAreaInput(session = session, inputId = 'sd', value = "")
updateTextAreaInput(session = session, inputId = 'sd1', value = "")
})

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)
})
}

Shiny Dashboard: Render multiple menu items and output dynamic content to each

I need to render various menu sub-items based on some reactive data values. For each sub-item, I also need to associate linked output. I tried to link with tabName, but not sure what went wrong.
Below is an example. The desired output will be one box for each menu item/sub-item.
## This code snippet doesn't do what I need ----
shinyApp(
ui = dashboardPage(
dashboardHeader(),
dashboardSidebar(
sidebarMenu(
menuItemOutput("dynamic_menu"),
menuItem("Menu2", tabName = "menu2")
)
),
dashboardBody(
tabItems(
uiOutput("menu1_content"),
tabItem(tabName = "menu2", box("I am menu2"))
)
),
title = "Example"
),
server = function(input, output) {
output$dynamic_menu <- renderMenu({
submenu_list <- lapply(letters[1:5], function(x) {
menuSubItem(x, tabName = paste0("menu1-", x))
})
menuItem(
text = "Menu1",
startExpanded = TRUE,
do.call(tagList, submenu_list)
)
})
output$menu1_content <- renderUI({
content_list <- lapply(letters[1:5], function(x) {
tabItem(
tabName = paste0("menu1-", x),
box(x)
)
})
do.call(tagList, content_list)
})
}
)
## This code snippet does what I need ----
shinyApp(
ui = dashboardPage(
dashboardHeader(),
dashboardSidebar(
sidebarMenu(
menuItem(
"Menu1", startExpanded = TRUE,
menuSubItem("a", tabName = "menu1-a"),
menuSubItem("b", tabName = "menu1-b"),
menuSubItem("c", tabName = "menu1-c"),
menuSubItem("d", tabName = "menu1-d"),
menuSubItem("e", tabName = "menu1-e")
),
menuItem("Menu2", tabName = "menu2")
)
),
dashboardBody(
tabItems(
tabItem(tabName = "menu1-a", box("a")),
tabItem(tabName = "menu1-b", box("b")),
tabItem(tabName = "menu1-c", box("c")),
tabItem(tabName = "menu1-d", box("d")),
tabItem(tabName = "menu1-e", box("e")),
tabItem(tabName = "menu2", box("I am menu2"))
),
title = "Example"
)
),
server = function(input, output) {}
)
Answering my own question, but feel free to jump in if you have something more elegant.
I think my initial understanding of shiny dashboard is wrong, causing the app structure to be invalid.
The trick here is to add id to the sidebarMenu, so that page focus could be tracked and parsed later. Then each of the render function will listen on the input and render associated content.
shinyApp(
ui = dashboardPage(
dashboardHeader(),
dashboardSidebar(
sidebarMenu(
id = "sidebar_menu",
menuItemOutput("dynamic_menu"),
menuItem("Menu2", tabName = "menu2")
)
),
dashboardBody(
uiOutput("menu1_content"),
uiOutput("menu2_content")
),
title = "Example"
),
server = function(input, output, session) {
output$dynamic_menu <- renderMenu({
menu_list <- lapply(letters[1:5], function(x) {
menuSubItem(x, tabName = paste0("menu1-", x))
})
menuItem(
text = "Menu1",
startExpanded = TRUE,
do.call(tagList, menu_list)
)
})
output$menu1_content <- renderUI({
sidebar_menu <- tstrsplit(input$sidebar_menu, "-")
if (sidebar_menu[[1]] == "menu1") box(sidebar_menu[[2]])
})
output$menu2_content <- renderUI({
sidebar_menu <- tstrsplit(input$sidebar_menu, "-")
if (sidebar_menu[[1]] == "menu2") box("I am menu2")
})
}
)

Adding static login page to R shiny dashboard

I have this initial shiny dashboard that I assembeled together:
## app.R ##
library(shiny)
library(shinydashboard)
library(readxl)
ui <- dashboardPage(
dashboardHeader(dropdownMenuOutput("messageMenu"),
dropdownMenuOutput("notificationMenu")),
dashboardSidebar(
sidebarMenu(
menuItem("Dashboard", tabName = "dashboard", icon = icon("dashboard")),
menuItem("ImportForcast", tabName = "ImportForcast", icon = icon("arrow-down")),
menuItem("Visualization", tabName = "Visualization", icon = icon("dashboard")),
menuItem("Help", tabName = "Help", icon = icon("list-alt") ),
menuItem("Widgets", tabName = "widgets", icon = icon("th"))
)
),
## Body content
dashboardBody(
tabItems(
# First tab content
tabItem(tabName = "dashboard",
fluidRow(
box(plotOutput("plot1", height = 250)),
box(
title = "Controls",
sliderInput("slider", "Number of observations:", 1, 100, 50)
)
)
),
tabItem(tabName = "ImportForcast",
fluidRow(
span(headerPanel("Import forcast file"), style="color:red"),
sidebarPanel(
radioButtons("pdt", "Choisir produit:",
c("Option1" = "Option1",
"Option2" = "Option2")),
fileInput('file1', 'Choose CSV File',
accept=c('text/csv', 'text/comma-separated-values,text/plain', '.csv')),
tags$hr()
),
actionButton("do", "Export/View"),
dataTableOutput('table'),
mainPanel(
# dygraphOutput("hdpePlot"),
textOutput("text"),
tableOutput('contents')
)
)
),
tabItem(tabName = "Visualization",
titlePanel("Forcast Dataset"),
sidebarLayout(
sidebarPanel(
radioButtons("x", "Select X-axis:",
list("date"='a')),
radioButtons("y", "Select Y-axis:",
list('X000'='f', "inflation"='b',"X004"='c',"X008"='d', "X009"='e','X014'='j'))
),
mainPanel(
textOutput("msg"),
plotOutput("distPlot")
)
)
),
tabItem(tabName = "Help",
fluidRow(
h2(" Help : "),
h1(" Installation guide : "),
h3(" Contact : "),
box(title = "Histogram", status = "primary", plotOutput("plot2", height = 250)),
box(
title = "Inputs", status = "warning",
"Box content here", br(), "More box content",
sliderInput("slider", "Slider input:", 1, 100, 50),
textInput("text", "Text input:")
),
box(
title = "Histogram", background = "maroon", solidHeader = TRUE,
plotOutput("plot4", height = 250)
),
box(
title = "Inputs", background = "black",
"Box content here", br(), "More box content",
sliderInput("slider", "Slider input:", 1, 100, 50),
textInput("text", "Text input:")
)
)
),
# Second tab content
tabItem(tabName = "widgets",
h2("Widgets tab content")
)
)
)
)
#Server
server <- function(input, output) {
histdata <- rnorm(500)
output$plot1 <- renderPlot({
data <- histdata[seq_len(input$slider)]
hist(data)
})
#Show success message if data is successfuly imported
output$text<- reactive({
validate(
need(is.null(input$file1) , "Import Success")
)
"Not imported file yet"
})
#Show msg that inform the user that he must import file before visualization
output$msg<- reactive({
validate(
need(!is.null(input$file1) , "You must import file for visualization")
)
"Enjoy visualisation"
})
output$dataForcast<- reactive({
dataForcast<- read_excel(input$file1)
})
dataForcast <- read_excel("./Forcast.xlsx",
sheet = 1, na = "NA",
skip = 1)
output$table <- renderDataTable(dataForcast)
# Saving files
saveRDS(dataForcast,file="./forcast/RDS/dataForcast.Rds")
write.csv(dataForcast, file = "./forcast/RDS/dataForcastt.csv", row.names = FALSE)
df <- eventReactive(input$do, {
dataForcast <- read_excel("./Forcast.xlsx",
sheet = 1, na = "NA",
skip = 1)
output$table <- renderDataTable(dataForcast)
})
# output$do<- reactive({
#
# output$table <- renderDataTable(dataForcast)
# })
#The visualisation of the data
output$distPlot<- renderPlot({
if(!is.null(input$file1) )
{
if(input$x=='a'){
i<-1}
if(input$y=='b'){
j<-54}
if(input$y=='c'){
j<-4}
if(input$y=='d'){
j<-9}
if(input$y=='e'){
j<-10 }
if(input$y=='f'){
j<-2 }
if(input$y=='j'){
j<-14 }
s <- dataForcast[, i]
k <- dataForcast[, j]
x2 <- data.frame(s,k)
plot(x2)
}
})
#Notification is generated on the server
output$notificationMenu <- renderMenu({
#Initalisation of notification
col_headings <- c('message','status')
# notificationData <- data.frame(' 12 items delivered', 'success')
notificationData<- read.csv('msgs.csv')
names(notificationData) <- col_headings
#add a notification of success importation
if(!is.null(input$file1))
{
not_sucess<- data.frame('Import Success', 'success')
names(not_sucess) <- col_headings
notificationData<-rbind(not_sucess, notificationData)
}
nots <- apply(notificationData, 1, function(row) {
notificationItem(text = row[["message"]], status = row[["status"]])
})
dropdownMenu(type = "notifications", .list = nots)
})
#Message is generated on the server
output$messageMenu<- renderMenu({
dropdownMenu(type = "messages",
messageItem(
from = "Sales Dept",
message = "Sales are steady this month."
),
messageItem(
from = "New User",
message = "How do I register?",
icon = icon("question"),
time = "13:45"
),
messageItem(
from = "Support",
message = "The new server is ready.",
icon = icon("life-ring"),
time = "2014-12-01"
)
)
})
}
shinyApp(ui, server)
I tried to add a login page but it was not succesfull :
library(shiny)
library(shinydashboard)
source("admin.R")
my_username <- c("test","admin")
my_password <- c("test","123")
get_role=function(user){
if(user=="test") {
return("TEST")
}else{
return("ADMIN")
}
}
get_ui=function(role){
itog=list()
if(role=="TEST"){
itog$title=test_title
itog$main=test_main
itog$side=test_side
return(itog)
}else{
itog$title=admin_title
itog$main=admin_main
itog$side=admin_side
return(itog)
}
}
shinyServer(function(input, output,session) {
USER <- reactiveValues(Logged = FALSE,role=NULL)
ui1 <- function(){
tagList(
div(id = "login",
wellPanel(textInput("userName", "Username"),
passwordInput("passwd", "Password"),
br(),actionButton("Login", "Log in")))
,tags$style(type="text/css", "#login {font-size:10px; text-align: left;position:absolute;top: 40%;left: 50%;margin-top: -10px;margin-left: -150px;}")
)}
observe({
if (USER$Logged == FALSE) {
if (!is.null(input$Login)) {
if (input$Login > 0) {
Username <- isolate(input$userName)
Password <- isolate(input$passwd)
Id.username <- which(my_username == Username)
Id.password <- which(my_password == Password)
if (length(Id.username) > 0 & length(Id.password) > 0) {
if (Id.username == Id.password) {
USER$Logged <- TRUE
USER$role=get_role(Username)
}
}
}
}
}
})
observe({
if (USER$Logged == FALSE) {
output$page <- renderUI({
box(
div(class="outer",do.call(bootstrapPage,c("",ui1()))))
})
}
if (USER$Logged == TRUE) {
output$page <- ui # ui from the first dashboard
}
})
})
With the second code I get the login box as in the following screen capture:
After I change this block :
if (USER$Logged == TRUE) {
output$page <- ui # ui from the first dashboard
}
I get the new interface on displayed but the old side menu is still there, so it's dashboard inside of another dashboard, because I just integrated the whole interface in just output$page.
Is there an easier solution to add login page to the first dashboard ?
Or a way to integrate the login (second code) with the first dashboard (first code) so the user can login and the dashboard is displayed?

Resources