I'm having some trouble with setting out the layout of my shiny app. After trying a couple of different options the one to work the best for me was the navbarPage. Although, I managed to solve the majority of my problems(with the help of stackoverflow) I'm stuck in one.
Basically, I have a table that has many columns and it ends up always larger than the wellPanel that contains the table.
Below is some code to illustrate the problem:
require(shiny)
require(shinythemes)
side_width <- 5
sidebar_panel <-
sidebarPanel(
width = side_width,
radioButtons("Radio1",
label = h4("Radio label 1"),
choices = list("Europe" = "EU",
"USA" = "US"),
selected = "EU"),
hr()
br()
radioButtons("Radio 2",
label = h4("Radio label 2"),
choices = list("Annual" = 1, "Monthly" = 12),
selected = 1)
)
main_panel <- mainPanel(
width = 12 - side_width,
wellPanel(
h5(helpText("Figure 1: ..."))
),
wellPanel(
h5(helpText("Table 1: ..."))
),
wellPanel(
h5(helpText("Table 2: ..."))
),
wellPanel(
fluidRow(
column(12,
h5(helpText("Table 3: ..."))
)
)
)
)
# user interface
ui <- shiny::navbarPage("testing shiny",
tabPanel("Tab1",
sidebarLayout(
sidebarPanel = sidebar_panel,
mainPanel = main_panel,
position = "left")
),
tabPanel("Tab2",
verbatimTextOutput("summary")
),
tags$style(type="text/css", "body {padding-top: 70px;}"),
theme=shinytheme("cosmo"),
position ="fixed-top"
)
server <- function(input, output) {
}
shinyApp(ui = ui, server = server)
When you run the code you will see the current layout. All would be fine if it wasn't for that massive wide table 3 which half of it is always out of the wellPanel.
My question is is it possible to extend the wellPanel to the left so it occupies the entire width of the layout?
Any pointers are highly appreciated.
Cheers
The fluidRow and column functions don't do anything inside the wellPanel/mainPanel - you want to put this particular wellPanel as its own fluidRow separate from the sidebar layout.
Additionally, if your table is being made in the DT package, you can add scrollX=TRUE to the render options so that it'll add a scroll bar if the table is too big to fit.
require(shiny)
require(shinythemes)
side_width <- 5
# user interface
ui <- navbarPage(
"testing shiny",
tabPanel("Tab1",
sidebarLayout(position = "left",
sidebarPanel(width = side_width,
radioButtons("Radio1",
label = h4("Radio label 1"),
choices = list("Europe" = "EU",
"USA" = "US"),
selected = "EU"),
hr(),
br(),
radioButtons("Radio 2",
label = h4("Radio label 2"),
choices = list("Annual" = 1, "Monthly" = 12),
selected = 1)),
mainPanel(
width = 12 - side_width,
wellPanel(
h5(helpText("Figure 1: ..."))
),
wellPanel(
h5(helpText("Table 1: ..."))
),
wellPanel(
h5(helpText("Table 2: ..."))
)
)
),
fluidRow(
column(12,
wellPanel(
h5(helpText("Table 3: ..."))
)
)
)
),
tabPanel("Tab2",
verbatimTextOutput("summary")),
tags$style(type = "text/css", "body {padding-top: 70px;}"),
theme = shinytheme("cosmo"),
position = "fixed-top"
)
Related
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")
)
)
I am trying to center-align tabsetpanel "pills" on shiny, but it alwais get on left position. Here is the code example, anyone knows how to align this buttons or pills center?
library(shiny)
ui <- fluidPage(
tabPanel(title = "Hello world", value = "HB",
tabsetPanel(id="subtabs", type="pills",
tabPanel(title = "TAB 1", value = "ILPF",
br(),
h4("I like Pink floyd, my favourite album is 'The dark side of the moon'", style = "color:grey", align = "center"),
br()
),
tabPanel(title = "TAB 2", value = "FS",
br(),
h4("But my favourite song is 'Shine on you crazy diamond'", style = "color:grey", align = "center"),
br()
)
)
)
)
server <- function(input, output, session) {}
shinyApp(ui = ui, server = server)
The pills should be in the middle of the page
You can do so by adding some CSS to your app. tags$style('ul.nav-pills{display: flex !important;justify-content: center !important;}') does the trick.
library(shiny)
ui <- fluidPage(
tags$head(
tags$style('
ul.nav-pills{
display: flex !important;
justify-content: center !important;
}')
),
tabPanel(title = "Hello world", value = "HB",
tabsetPanel(id="subtabs", type="pills",
tabPanel(title = "TAB 1", value = "ILPF",
br(),
h4("I like Pink floyd, my favourite album is 'The dark side of the moon'", style = "color:grey", align = "center"),
br()
),
tabPanel(title = "TAB 2", value = "FS",
br(),
h4("But my favourite song is 'Shine on you crazy diamond'", style = "color:grey", align = "center"),
br()
)
)
)
)
server <- function(input, output, session) {}
shinyApp(ui = ui, server = server)
My Shiny app has a universal sidebarPanel. I want to hide it for one particular tab, i.e. whenever the used would navigate to that tab the sidebarPanel would collapse. The code I am trying is as follows-
The UI-
library(shiny)
shinyUI(fluidPage (
theme = shinytheme("superhero"),
headerPanel("COVID-19 Data Visualizer"),
sidebarPanel(
width = 2,
selectInput(
"countries",
label = "Select Countries",
choices =
c("B", "C", "A"),
selected = c("A"),
multiple = T
),
submitButton(text = "View")
),
mainPanel (h1(""),
tabsetPanel(
tabPanel(
"Global Status",
div(id="Main"),
plotlyOutput("figG"),
br(),
plotlyOutput("global_time"),
br(),
plotlyOutput("global_cfr"),
br(),
plotlyOutput("global_p"),
br(),
plotlyOutput("global_recov_dead")
),
tabPanel(
"Comparative Charts",
plotlyOutput("fig_confirm"),
br(),
plotlyOutput("fig_dead"),
br(),
plotlyOutput("fig_recov")
),
tabPanel(
"Ratio Analysis",
plotlyOutput("fig_confirm_S"),
br(),
plotlyOutput("fig_confirm_D"),
br(),
plotlyOutput("fig_Ratio"),
br(),
plotlyOutput("fig_cfr_print")
)
))
))
The server part-
server <- function(input, output) {
observeEvent(input$tabs == "Global Status", {
shinyjs::hide(id = "Main")
})
}
I don't really want to use the navbarPage and want single sidebarPanel for all the inputs.
A screenshot of the output I am getting-
Thanks in advance.
Here is an example:
library(shiny)
library(shinyjs)
ui <- fluidPage(
useShinyjs(),
sidebarLayout(
sidebarPanel(
id="sidebar",
selectInput(
"countries", label = "Select Countries",
choices = c("B", "C", "A"), selected = "A",
multiple = TRUE
)
),
mainPanel(
tabsetPanel(
tabPanel(
"Global status",
sliderInput("s1", "slider 1", 0, 100, 20)
),
tabPanel(
"Comparative charts",
sliderInput("s2", "slider 2", 0, 100, 50)
),
tabPanel(
"Ratio analysis",
sliderInput("s3", "slider 3", 0, 100, 80)
),
id = "tabset"
),
id="main"
)
)
)
server <- function(input, output){
observeEvent(input[["tabset"]], {
if(input[["tabset"]] == "Comparative charts"){
hideElement(selector = "#sidebar")
removeCssClass("main", "col-sm-8")
addCssClass("main", "col-sm-12")
}else{
showElement(selector = "#sidebar")
removeCssClass("main", "col-sm-12")
addCssClass("main", "col-sm-8")
}
})
}
shinyApp(ui = ui, server = server)
I'm trying to code an app with tabs in Shiny that makes reference to the same input from a text box.
Input:
column(2, textInput(inputId = "sh1", label = "Stakeholder #1's name"))
Output:
tabPanel("#1 vs #2",
fluidRow(
column(3),
column(2, textOutput(outputId = "sh1o")),
column(2, "vs"),
column(2, textOutput(outputId = "sh2o"))
),
tabPanel("#1 vs #3",
fluidRow(
column(3),
column(2, textOutput(outputId = "sh1o")),
column(2, "vs"),
column(2, textOutput(outputId = "sh3o"))
),
Rendering:
output$sh1o <- renderText(input$sh1)
As I have learn, Shiny wont allow an input to be used more than once.
Is there any way to make this work?
Can the same input get assigned to a temp variable and then to the output?
Shiny allows input to be used as many times as you want, but you can't use the same outputId for output elements. You could rename your textOutput outputIds by adding the name of the tab first to make them unique.
Here's an example:
library(shiny)
ui<-shinyUI(pageWithSidebar(
headerPanel("Test"),
sidebarPanel(textInput(inputId = "sh1", label = "Stakeholder #1's name")),
mainPanel(
tabsetPanel(
tabPanel("#1 vs #2",
fluidRow(
column(3),
column(2, textOutput(outputId = "tab1_sh1o")),
column(2, "vs"),
column(2, textOutput(outputId = "tab1_sh2o"))
)),
tabPanel("#1 vs #3",
fluidRow(
column(3),
column(2, textOutput(outputId = "tab2_sh1o")),
column(2, "vs"),
column(2, textOutput(outputId = "tab2_sh3o"))
)
)
))))
server <- function(input,output,session){
output$tab1_sh1o <- renderText(input$sh1)
output$tab1_sh2o <- renderText(input$sh1)
output$tab2_sh1o <- renderText(input$sh1)
output$tab2_sh3o <- renderText(input$sh1)
}
shinyApp(ui,server)
I have a couple of questions regarding R shiny Dashboard.
ui.R
library(shinydashboard)
library(shiny)
dashboardPage(
dashboardHeader(title = 'Test Interface'),
dashboardSidebar(width = 600,
h3('-------Input Data-------'),
fluidRow(
column(6, div(style = "height:10px"), fileInput(inputId = 'FileInput', label = 'Upload Input:', accept = c('csv','tsv','txt'))),
column(2, div(style = "height:3px"), checkboxInput(inputId = 'header', label = 'Header', value = FALSE)),
column(2, div(style = "height:12px"), radioButtons(inputId = 'sep', label = 'Separator', choices = c(comma=',',tab="\t",space=' '), selected = ","),offset = 1)
),
fluidRow(column(6, div(style = "height:1px"), fileInput(inputId = 'FileInput1', label = 'Upload Second Input:'))),
br(),
h3('-------Select Foreground-------'),
fluidRow(
column(5, div(style = "height:17px"), radioButtons(inputId = 'cutoff', label = 'Selection', choices = c('Up'='pos','Down'='neg','Both'='both'))),
br(),
column(3, div(style = "height:1px"), textInput(inputId = 'fc', label = "Fold Change", value = '0')),
column(3, div(style = "height:1px; margin-left:10cm"), height = 6,textInput(inputId = 'pvalue', label = "Adj. Pvalue",value = '0.05'))
),
fluidRow(column(2, h1(" "), actionButton(inputId = 'select', label = "Select Data"))),
fluidRow(column(5, div(style = "height:25px;font-color:blue"), downloadButton('download', 'Download Plot')))),
dashboardBody(
tabsetPanel(type="tabs", id = "tabvalue",
tabPanel(title = "Input Table", value = 'tab1', DT::dataTableOutput('table')),
tabPanel(title = "Plot", value = 'tab7', plotOutput('plot',width = 800,height = 800)))))
server.R
library(shiny)
shinyServer(function(input, output, session){
})
I couldn't figure out how to add a vertical scroll bar to the dashboardSidebar. In my actual app, the last elements are not visible when I run the app.
Thanks!
I ran into this and came up with the following hack (and I do mean hack).
shinyDashboard(
tags$head(
tags$style(HTML(".sidebar {
height: 90vh; overflow-y: auto;
}"
) # close HTML
) # close tags$style
), # close tags#Head
# ...
The 90vh sets the sidebar height at 90% of the viewport height. You may want to adjust this to taste. Too large a percentage and some of the sidebar still drops below the horizon; too small a percentage and the sidebar ends noticeably before the main body (with the scrollbar appearing prematurely).