I have an R shiny app with different download buttons as illustrated in the code below. The issue is that the position of the download button within fluidRow is not automatically aligned with the positions of other input elements like dateInput below.
ui <- dashboardPage(
title = "Test Dashboard", # this is the name of the tab in Chrome browserr
dashboardHeader(title = "Web Portal"),
dashboardSidebar(
sidebarMenu(
menuItem('Retail', tabName = "retail", icon = icon("th"),
menuItem('Dashboard', tabName = 'retail_dashboard'))
)
),
dashboardBody(
tabItem(tabName = "retail_dashboard",
tabsetPanel(type = "tabs",
tabPanel("Dashboard",
h3("Test."),
fluidRow(column(2,
dateInput("idx_muni_tot_ret_start_dt", label = "Start Date:", value = Sys.Date()-10)), # 1yr ago
column(2,
dateInput("idx_muni_tot_ret_end_dt", label = "End Date:", value = Sys.Date())),
column(2,
downloadButton("download_idx_muni_TR_data","Download Data"))
)
)
)
)
)
)
server <- function(input, output, session) {
# code...
}
cat("\nLaunching 'shinyApp' ....")
shinyApp(ui, server)
I found similar questions here How do I align downloadButton and ActionButton in R Shiny app? and here Change download button position in a tab panel in shiny app but they don't seem to answer my questions. I also attach a screenshot with the current button position as well as the expected one.
A workaround is to simulate a label on top of the download button and add 5px of margin-bottom.
column(
width = 2,
div(tags$label(), style = "margin-bottom: 5px"),
div(downloadButton("download_idx_muni_TR_data", "Download Data"))
)
A bit of css does the trick:
ui <- dashboardPage(
title = "Test Dashboard",
dashboardHeader(title = "Web Portal"),
dashboardSidebar(
),
dashboardBody(
h3("Test."),
fluidRow(column(2,
dateInput("idx_muni_tot_ret_start_dt",
label = "Start Date:", value = Sys.Date() - 10)),
column(2,
dateInput("idx_muni_tot_ret_end_dt",
label = "End Date:", value = Sys.Date())),
column(2,
div(style = "margin-bottom:15px",
downloadButton("download_idx_muni_TR_data","Download Data")))
, style = "display:flex;align-items:end")
)
)
Update
If you want to add a selectInput you need yet some new css tweaks to get the input on the same line:
ui <- dashboardPage(
title = "Test Dashboard",
dashboardHeader(title = "Web Portal"),
dashboardSidebar(),
dashboardBody(
h3("Test."),
fluidRow(column(2,
dateInput("idx_muni_tot_ret_start_dt",
label = "Start Date:", value = Sys.Date() - 10)),
column(2,
dateInput("idx_muni_tot_ret_end_dt",
label = "End Date:", value = Sys.Date())),
column(2,
tagAppendAttributes(selectInput("slc", "Select", LETTERS), style="margin-bottom:10px")),
column(2,
div(style = "margin-bottom:15px",
downloadButton("download_idx_muni_TR_data","Download Data"))),
style = "display:flex;align-items:end")
)
)
Related
I have at least 2 individual apps that I want to join in one single app. Although I was using shinyDashboard, I think that it could be a good idea to try with navbarPage.
However, I don't know if it is possible to do what I want with this new approach.
To put you in a context, this is an example of my shinyDashboard. Each tab has a sidebarPanel and mainPanel. I replicated the info in all the tabs, but the idea is that each tab has different things.
However, I was thinking to have this using navbarPage. Do you know if it is possible?
Here I attach you the code that I used for the shinyDashboard:
library(shiny)
library(shinydashboard)
library(shinyWidgets)
ui <- dashboardPage(
dashboardHeader(title = "Basic dashboard"),
## Sidebar content
dashboardSidebar(
sidebarMenu(
menuItem("Tab1", tabName = "Tab1", icon = icon("th")),
menuItem("Tab2", tabName = "Tab2", icon = icon("th")),
menuItem("Tab3", tabName = "Tab3", icon = icon("th"))
)
),
dashboardBody(
fluidRow(
tabItems(
tabItem(tabName = "Tab1",
sidebarPanel(
numericInput("num",
"Select a number",
min = 1,
value = 10),
checkboxInput("remove", "Remove...", value = FALSE),
sliderInput("slider", "slider", min = 1, max = 30, value=22)
),
mainPanel(
plotOutput("plot1")
)
),
tabItem(tabName = "Tab2",
sidebarPanel(
numericInput("num2",
"Select a number",
min = 1,
value = 10),
checkboxInput("remove2", "Remove...", value = FALSE),
sliderInput("slider2", "slider", min = 1, max = 30, value=22)
),
mainPanel(
plotOutput("plot2")
)
),
tabItem(tabName = "Tab3",
sidebarPanel(
numericInput("num3",
"Select a number",
min = 1,
value = 10),
checkboxInput("remove3", "Remove...", value = FALSE),
sliderInput("slider3", "slider", min = 1, max = 30, value=22)
),
mainPanel(
plotOutput("plot3")
)
)
)
)
)
)
server <- function(input, output, session) {
output$plot1 <- renderPlot({
plot(x=c(1,2,3,4,5,6), y=c(14,3,6,4,56,2))
})
output$plot2 <- renderPlot({
plot(x=c(1,2,3,4,5,6), y=c(14,3,6,4,56,2))
})
output$plot3 <- renderPlot({
plot(x=c(1,2,3,4,5,6), y=c(14,3,6,4,56,2))
})
}
shinyApp(ui, server)
And the code for the navbarPage approach:
library(shinythemes)
library(shiny)
ui <- fluidPage(theme = shinytheme("flatly"),
navbarPage(
collapsible = T,
fluid = T,
"",
tabPanel("Tab 1", "one"),
tabPanel("Tab 2", "two"),
tabPanel("Tab 3", "three"),
)
)
server <- function(input, output, session) {
}
shinyApp(ui, server)
Thanks very much in advance
You can do that with sidebarLayout. Here I've done it for the first tabPanel:
library(shinythemes)
library(shiny)
ui <- fluidPage(
theme = shinytheme("flatly"),
navbarPage(
title = "Your App Title",
collapsible = TRUE,
fluid = TRUE,
tabPanel(
title = "Tab 1",
sidebarLayout(
sidebarPanel = sidebarPanel(
tags$h3(
"Sidebar Content Here!"
)
),
mainPanel = mainPanel(
tags$h3(
"Main Panel Content Here!"
)
)
)
),
tabPanel(
title = "Tab 2",
"three"
),
)
)
server <- function(input, output, session) {
}
shinyApp(ui, server)
I am building a shiny dashboard and want to include a slider bar with a dynamic range of values. To do this I am generating the sliderInput on the server and displaying it with renderUI/uiOuput. In the example below this works fine if I only include the slider on one tabPanel. However, when I attempt to add it to a second tabPanel it fails to render on either.
This post describes a similar problem but the solution (suspendWhenHidden = FALSE) does not work for me. I also tried the solution from this post although the issue there was somewhat different.
library(shinydashboard)
library(shiny)
ui <- dashboardPage(
dashboardHeader(title = "Demo dashboard"),
dashboardSidebar(
sidebarMenu(
menuItem("Overview", tabName = "overview", icon = icon("dashboard"))
)
),
dashboardBody(
tabItems(
tabItem(tabName = "overview",
fluidRow(
column(width = 6,
tabBox(
title = "Tab box",
width = "100%",
id = "tabset1", height = "250px",
tabPanel("Tab 1",
img(src = "test_img.jpg", height="100%", width="100%", align="center"),
# the slider is rendered properly if only included in a single tab
uiOutput("out_slider")
),
tabPanel("Tab 2",
img(src = "test_img.jpg", height="100%", width="100%", align="center"),
# however, uncommenting below causes the slider to not render on *either* tab
#uiOutput("out_slider")
)
)
)
)
)
)
)
)
server <- function(input, output) {
startDate <- as.Date("2019-01-01","%Y-%m-%d")
endDate <- as.Date("2020-01-01","%Y-%m-%d")
# from https://stackoverflow.com/q/36613018/11434833 ... does not seem to fix problem
# output$out_slider <- renderUI({})
# outputOptions(output, "out_slider", suspendWhenHidden = FALSE)
output$out_slider <- renderUI({
sliderInput("slider1", label = h3("Slider"), min = startDate,
max = endDate, value = endDate,timeFormat="%e %b, %y")
})
}
shinyApp(ui, server)
As mentioned by YBS, there is a conflict in the ID.
Try creating modules like shown below.
library(shinydashboard)
library(shiny)
slider<-function(id){
ns<-NS(id)
tagList(
uiOutput(ns("out_slider"))
)
}
sliderServer<-function(id, label, min,
max , value, timeFormat="%e %b, %y"){
moduleServer(
id,
function(input,output,session){
output$out_slider <- renderUI({
sliderInput("slider", label , min,
max, value, timeFormat="%e %b, %y")
})
}
)
}
ui <- dashboardPage(
dashboardHeader(title = "Demo dashboard"),
dashboardSidebar(
sidebarMenu(
menuItem("Overview", tabName = "overview", icon = icon("dashboard"))
)
),
dashboardBody(
tabItems(
tabItem(tabName = "overview",
fluidRow(
column(width = 6,
tabBox(
title = "Tab box",
width = "100%",
id = "tabset1", height = "250px",
tabPanel("Tab 1",
img(src = "test_img.jpg", height="100%", width="100%", align="center"),
# the slider is rendered properly if only included in a single tab
slider("tab1")
),
tabPanel("Tab 2",
img(src = "test_img.jpg", height="100%", width="100%", align="center"),
# however, uncommenting below causes the slider to not render on *either* tab
slider("tab2")
)
)
)
)
)
)
)
)
server <- function(input, output) {
startDate <- as.Date("2019-01-01","%Y-%m-%d")
endDate <- as.Date("2020-01-01","%Y-%m-%d")
sliderServer("tab1",label = h3("Slider"), min = as.Date("2019-01-01","%Y-%m-%d"),
max = as.Date("2020-01-01","%Y-%m-%d"), value = as.Date("2020-01-01","%Y-%m-%d"), timeFormat="%e %b, %y")
sliderServer("tab2", label = h3("Slider"), min = as.Date("2019-01-01","%Y-%m-%d"),
max = as.Date("2020-01-01","%Y-%m-%d"), value = as.Date("2020-01-01","%Y-%m-%d"), timeFormat="%e %b, %y")
}
shinyApp(ui, server)
If you intend to pass reactive values in the sliderServer function, please wrap it in observeEvent.
There is a wrong display in shiny dashboard for the below code. The title "Yet to do" is getting displayed as soon as i run the app. I need that when I click on Bivariate Analysis. What is the issue here. This happened when I introduced selectinput under menu item. Earlier it was working well
library(shinydashboard)
library(shiny)
ui <- dashboardPage(
dashboardHeader(title = "Data Analysis"),
dashboardSidebar(
sidebarMenu(
menuItem("Univariate Analysis", tabName = "Univariate", icon =
icon("question"),selectInput("Factors",h5("Factors"),choices =
c("","A","B"))),
menuItem("Bivariate Analysis", tabName = "Bivariate", icon =
icon("question")))
),
dashboardBody(
tabItems(
tabItem(tabName = "Univariate",fluidRow(box(plotOutput("Plot1"),width =
1000,height = 1000),
box(plotOutput("Plot2"),width =
1000,height = 1000))),
tabItem(tabName = "Bivariate",h1("Yet to do")))
))
server <- function(input, output) {
}
shinyApp(ui, server)
It is related having selectInput() as menuItem(). I tried some options like creating menuSubItem etc. but couldn't get it to work. This is probably some bug so you may have to look around for a fix. For now, I'd suggest moving the selectInput inside dashboardBody() -
ui <- dashboardPage(
dashboardHeader(title = "Data Analysis"),
dashboardSidebar(
sidebarMenu(
menuItem("Univariate Analysis",
tabName = "Univariate", icon = icon("question")
# removing selectInput from here fixes the issue
# ,selectInput("Factors", h5("Factors"), choices = c("","A","B"))
),
# an option is to have selectInput by itself but probably not the layout you want
# selectInput("Factors", h5("Factors"), choices = c("","A","B")),
menuItem("Bivariate Analysis",
tabName = "Bivariate", icon = icon("question")
)
)
),
dashboardBody(
tabItems(
tabItem(tabName = "Univariate",
fluidRow(
# add selectInput somewhere on Univariate page
selectInput("Factors", h5("Factors"), choices = c("","A","B")),
box(plotOutput("Plot1"), width = "50%", height = "50%"),
box(plotOutput("Plot2"), width = "50%", height = "50%")
)
),
tabItem(tabName = "Bivariate",
h1("Yet to do")
)
)
)
)
server <- function(input, output) {}
shinyApp(ui, server)
So I need to create action buttons in R shiny based on the number of rows in dataframe, upon googling for the solution now able to create the action buttons dynamically but I was not able to label it according to the values in the data frame.
Here is my UI.R
library(shiny)
library(shinydashboard)
library(DT)
shinyUI(
dashboardPage(
dashboardHeader(title = div(img(src="new.png", height = 40, width = 200),"IPT dashboard",width = 300)),
dashboardSidebar(
sidebarMenu(
menuItem("Dashboard", tabName = "dashboard", icon = icon("dashboard")),
menuItem("Vehicle Data", tabName = "VehicleData", icon = icon("table")),
menuItem("Driver Behaviour", tabName = "DriverBehaviour", icon = icon("th")),
menuItem("Vehicle Information", tabName = "Vehicleinfo", icon = icon("th")),
menuItem("Crash Report", tabName = "crashreport", icon = icon("th")),
menuItem("Emission Report", tabName = "Emissionreport", icon = icon("th")),
menuItem("Fuel Economy", tabName = "FuelEconomy", icon = icon("th")),
menuItem("View Location", tabName = "viewloc", icon = icon("th")),
menuItem("detctest", tabName = "dtctest", icon = icon("th"))
),
width = "200px"
),
dashboardBody(
tabItems(
tabItem("dashboard",
tabsetPanel(
tabPanel( title = "Real Time",
br(),
fluidRow(
box(
tags$head(
tags$style(HTML("
.box { overflow-y: auto; }
" )
)
),
height = "300px",
width =2,
h3("Trouble Code(s)", align="left"),
column(1, uiOutput("go_buttons"))
)
)#tabitemsclose
)#dashbodyclose
)#pageclose
)#uiclose
Server.R
library(shiny)
library(DT)
shinyServer(function(input,output)
{
options(digits = 22)
output$go_buttons <- renderUI({
mat <- as.data.frame(c("P01","p02","p03"))
buttons <- as.list(1:ncol(mat))
buttons <- lapply(buttons, function(i)
{
btName <- paste0(mat[i])
fluidRow(
br(),
column(2,actionButton(btName,paste(mat[i])))
)
})
})
When I execute the above scripts, It shows only one action button with the values as in the dataframe.
Expected output
Here in Server.R I am creating dataframe but in real time I will be fetching it through other calculation where the number of rows is not fixed which implies the number of action buttons are also not predefined, Number of action button will be equal to the number of rows in the data frame also, the label of action button should be same as the values in the data frame.
You only get one action button out, because your apply loop only has one number in it. You take 1:ncol(mat) eventhough your data.frame has only one column.
I changed two things:
I replaced buttons inside the lapply-function with 1:nrow(mat)
I used mat[i,1] because your values are in the rows. If in your data the values you want on the action buttons are in one vector you can keep using [i]
The app.r:
library(shiny)
library(shinydashboard)
library(DT)
### ui.r
ui <- shinyUI(dashboardPage(
dashboardHeader(title = div(img(src="new.png", height = 40, width = 200),"IPT dashboard",width = 300)),
dashboardSidebar(
sidebarMenu(
menuItem("Dashboard", tabName = "dashboard", icon = icon("dashboard")),
menuItem("Vehicle Data", tabName = "VehicleData", icon = icon("table")),
menuItem("Driver Behaviour", tabName = "DriverBehaviour", icon = icon("th")),
menuItem("Vehicle Information", tabName = "Vehicleinfo", icon = icon("th")),
menuItem("Crash Report", tabName = "crashreport", icon = icon("th")),
menuItem("Emission Report", tabName = "Emissionreport", icon = icon("th")),
menuItem("Fuel Economy", tabName = "FuelEconomy", icon = icon("th")),
menuItem("View Location", tabName = "viewloc", icon = icon("th")),
menuItem("detctest", tabName = "dtctest", icon = icon("th"))
),
width = "200px"
),
dashboardBody(tabItems(
tabItem("dashboard",
tabsetPanel(
tabPanel( title = "Real Time",
br(),
fluidRow(
box(
tags$head(
tags$style(HTML("
.box { overflow-y: auto; }
" )
)
),
height = "300px",
width =2,
h3("Trouble Code(s)", align="left"),
column(1, uiOutput("go_buttons"))
)))))
) #tabitemsclose
)#dashbodyclose
)#pageclose
) #uiclose
### server.r
server <- function(input, output, session){
options(digits = 22)
output$go_buttons <- renderUI({
mat <- as.data.frame(c("P01","p02","p03"),stringsAsFactors = FALSE)
buttons <- lapply(1:nrow(mat), function(i)
{
btName <- paste0(mat[i,1])
fluidRow(
br(),
column(2,actionButton(btName,paste(mat[i,1])))
)
})
return(buttons)
})
}
shinyApp(ui, server)
I have a shiny application, where in I am trying to provide a checkbox on top of a graph for the user to select. Currently, the check box is rendered below the title, whereas I want the title on the left hand side and the check box on the right hand side in the same line. I am sure it can be achieved through recoding CSS, but don't know how. The current code looks as follows:
library(shiny)
library(shinydashboard)
ui <- dashboardPage(
dashboardHeader(
title = "MODULE",titleWidth = 225
),
dashboardSidebar(
width = 225,
sidebarMenu(id = "tabs",
menuItem("TOPLINES", tabName = "tplines", icon = shiny::icon("dashboard"))
)),
dashboardBody(
tabItems(
tabItem(
tabName = "tplines",
fluidRow(
box(
checkboxInput(inputId = "inventorytop8metrocheck", "Add to reports", value = FALSE),
width = 6, status = "info", title = "Inventory information",
div(plotlyOutput("inventorytop8metro"), width = "100%", height = "400px", style = "font-size:80%;")
)
)))))
server <- function(session,input,output){
}
shinyApp(ui,server)
Maybe you are just looking for the standard row partition with columns. The title arguement takes any ui elements, so we input a row that is half your original title and half the checkbox input. Thus, they are in line. Of course, the checkbox then has the same style as the title. If you don't want that, you can alter the style by setting a style parameter in the checkbox column.
library(shiny)
library(shinydashboard)
library(plotly)
ui <- dashboardPage(
dashboardHeader(
title = "MODULE",titleWidth = 225
),
dashboardSidebar(
width = 225,
sidebarMenu(id = "tabs",
menuItem("TOPLINES", tabName = "tplines", icon = shiny::icon("dashboard"))
)),
dashboardBody(
tabItems(
tabItem(
tabName = "tplines",
fluidRow(
box(
width = 6, status = "info", title = fluidRow(
column(6, "Inventory information"),
column(6, checkboxInput(inputId = "inventorytop8metrocheck", "Add to reports", value = FALSE))
),
div(plotlyOutput("inventorytop8metro"), width = "100%", height = "400px", style = "font-size:80%;")
)
)
)
)
)
)
server <- function(session,input,output){}
shinyApp(ui,server)