Align Inputs with Labels and ActionButton vertically in fluidRow - r

In my shinydashboardPlus app, I use fluidRow/column to specify my layout. Sometimes, I have one or several textInput / selectInput and an actionButton in one row. Since the input elements do have a label, they are vertically larger than the button, which does not look very nice. For example:
Is there an easy way to move the actionButton a little below so that it is in line with, for example, the "local" element?
Here is a minimal example:
library(shiny)
library(shinydashboard)
library(shinydashboardPlus)
ui <- shinydashboardPlus::dashboardPage(
header=shinydashboardPlus::dashboardHeader(title = "Align Example"),
sidebar=shinydashboardPlus::dashboardSidebar(
shinydashboard::sidebarMenu(id = "tabs",
shinydashboard::menuItem(
"Welcome", tabName = "welcome"
)
)
),
body=shinydashboard::dashboardBody(
shinydashboard::tabItems(
shinydashboard::tabItem(tabName="welcome",
shiny::fluidRow(
shinydashboardPlus::box(
status="black", solidHeader = TRUE, width=12, closable = FALSE,
title="Welcome!",
shiny::column(4,
shiny::textInput("username", label="User Name:")
),
shiny::column(4,
shiny::passwordInput("passwd", label="Password:")
),
shiny::column(2,
shiny::selectInput(inputId="dbmode", "Modus:",
choices = c("production", "test", "local"),
selected = "local"
)
),
shiny::column(2,
shiny::actionButton("dbconnect", "Connect!")
)
)
)
)
)
)
)
server <- function(input, output, session) {
}
shiny::shinyApp(ui, server)

With the help of SelectorGadget and then searching SO for "margin-bottom", I found this post, which led me to
shiny::column(2,
shiny::actionButton(ns("dbconnect"), "Connect!"),
style = "margin-top:25px;" ## <-- !
)
Not sure if this is good practice, but I am happy for now.

The easiest way I can think of is to ad a br() before the action button:
library(shiny)
library(shinydashboard)
library(shinydashboardPlus)
ui <- shinydashboardPlus::dashboardPage(
header=shinydashboardPlus::dashboardHeader(title = "Align Example"),
sidebar=shinydashboardPlus::dashboardSidebar(
shinydashboard::sidebarMenu(id = "tabs",
shinydashboard::menuItem(
"Welcome", tabName = "welcome"
)
)
),
body=shinydashboard::dashboardBody(
shinydashboard::tabItems(
shinydashboard::tabItem(tabName="welcome",
shiny::fluidRow(
shinydashboardPlus::box(
status="black", solidHeader = TRUE, width=12, closable = FALSE,
title="Welcome!",
shiny::column(4,
shiny::textInput("username", label="User Name:")
),
shiny::column(4,
shiny::passwordInput("passwd", label="Password:")
),
shiny::column(2,
shiny::selectInput(inputId="dbmode", "Modus:",
choices = c("production", "test", "local"),
selected = "local"
)
),
shiny::column(2,
br(),
shiny::actionButton("dbconnect", "Connect!")
)
)
)
)
)
)
)
server <- function(input, output, session) {
}
shiny::shinyApp(ui, server)

Related

How to adjust width of well panel in Shiny?

Is there way to adjust the width of a well panel as shown in the image below? At the bottom is the code, if the user clicks the "Delete column" action button a conditional panel renders underneath; clicking of any other action button causes the conditional panel to disappear. I'd like the conditional panel to be surrounded in a well panel and am trying to format it nicely.
My guess is this requires some CSS.
Code:
library(shiny)
library(shinyjs)
ui <- fluidPage(
useShinyjs(),
br(),
fluidRow(
column(2,actionButton("addCol","Add column")),
column(2,actionButton("delCol","Delete column")),
column(2,actionButton("savTbl","Save table")),
column(2,actionButton("clrTbl","Clear table")),
br(),
),
br(),
shinyjs::hidden(
div(id="delPanel",
conditionalPanel(
condition="input.delCol > 0 && !output.hide_panel",
fluidRow(
wellPanel(
column(2,textOutput("delFlag")),
column(3,uiOutput("delCol2"))
)
),
style = "display: none;"
)
)
)
)
server <- function(input,output,session)({
observeEvent(input$delCol,{shinyjs::show("delPanel")})
observeEvent(input$addCol|input$savTbl|input$clrTbl,{shinyjs::hide("delPanel")})
output$delFlag <- renderText("Delete column:")
output$delCol2 <-
renderUI(
selectInput("delCol3",
label = NULL,
choices = c(1,2,3),
selected = "")
)
})
shinyApp(ui, server)
Below is a css solution, thanks to post Shiny wellpanel width:
library(shiny)
library(shinyjs)
ui <- fluidPage(
useShinyjs(),
br(),
fluidRow(
column(2,actionButton("addCol","Add column")),
column(2,actionButton("delCol","Delete column")),
column(2,actionButton("savTbl","Save table")),
column(2,actionButton("clrTbl","Clear table")),
br(),
),
br(),
shinyjs::hidden(
div(id="delPanel",
conditionalPanel(
condition="input.delCol > 0 && !output.hide_panel",
fluidRow(tags$div(id="pane", # added
wellPanel(
column(2,textOutput("delFlag")),
column(3,uiOutput("delCol2")),
),
tags$style(type="text/css","#pane{font-size:14px;width:565px;}") # added
)
),
style = "display: none;"
)
)
)
)
server <- function(input,output,session)({
observeEvent(input$delCol,{shinyjs::show("delPanel")})
observeEvent(input$addCol|input$savTbl|input$clrTbl,{shinyjs::hide("delPanel")})
output$delFlag <- renderText("Delete column:")
output$delCol2 <-
renderUI(
selectInput("delCol3",
label = NULL,
choices = c(1,2,3),
selected = "")
)
})
shinyApp(ui, server)

Show all object with renderUI

I'm working on a shiny app with dynamic rendering. When the user uncheck the box, he must have an output with 8 wellPanel and when the box is checked, he must have two wellPanel. I used the function renderUI to generate output but when the box is unchecked, I only have 4 wellPanel instead of 8. This is what I did :
library(shiny)
library(shinydashboard)
library(shinydashboardPlus)
body <- dashboardBody(
tabItems(
tabItem(tabName = "menutab1",
checkboxInput(inputId = "my_id", "check the box", value = TRUE),
####### renderUI #####
uiOutput("results")
)
)
)
ui <- dashboardPage(
title = "test",
options = list(sidebarExpandOnHover = TRUE),
header = dashboardHeader(disable = FALSE),
sidebar = dashboardSidebar(
minified = TRUE, collapsed = TRUE,
sidebarMenu(id="mymenu",
menuItem("first", tabName = "tab1", icon = icon("fas fa-acorn"),
menuSubItem('menu 1',
tabName = 'menutab1',
icon = icon('fas fa-hand-point-right'))
)
)
),
body
)
############# SERVER ############
server <- function(input, output) {
output$results <- renderUI({
if(input$my_id){
# object 1
fluidRow(
column(6,
wellPanel(
h1("A")
),
br(),
wellPanel(
h1("B")
)
)
)
} else {
# object 2 : doesnt show, why ?
fluidRow(
column(6,
wellPanel(
h1("C")
),
br(),
wellPanel(
h1("D")
)
),
column(6,
wellPanel(
h1("E")
),
br(),
wellPanel(
h1("F")
)
)
)
# object 3 : I only got this
fluidRow(
column(6,
wellPanel(
h1("H")
),
br(),
wellPanel(
h1("I")
)
),
column(6,
wellPanel(
h1("J")
),
br(),
wellPanel(
h1("K")
)
)
)
}
})
}
############# RUN #############
shinyApp(ui = ui, server = server)
How can we fix that ?
Some help would be appreciated
The problem with your above code is, that only the last object of the else statement is returned. You can wrap both fluidRows in a tagList to get the desired output.
library(shiny)
library(shinydashboard)
library(shinydashboardPlus)
body <- dashboardBody(tabItems(tabItem(
tabName = "menutab1",
checkboxInput(inputId = "my_id", "check the box", value = TRUE),
uiOutput("results")
)))
ui <- dashboardPage(
title = "test",
options = list(sidebarExpandOnHover = TRUE),
header = dashboardHeader(disable = FALSE),
sidebar = dashboardSidebar(
minified = TRUE,
collapsed = TRUE,
sidebarMenu(
id = "mymenu",
menuItem(
"first",
tabName = "tab1",
icon = icon("fas fa-acorn"),
menuSubItem(
'menu 1',
tabName = 'menutab1',
icon = icon('fas fa-hand-point-right')
)
)
)
),
body
)
server <- function(input, output) {
output$results <- renderUI({
if (input$my_id) {
fluidRow(column(6,
wellPanel(h1("A")),
br(),
wellPanel(h1("B"))
)
)
} else {
tagList(
fluidRow(
column(6,
wellPanel(h1("C")),
br(),
wellPanel(h1("D"))),
column(6,
wellPanel(h1("E")),
br(),
wellPanel(h1("F")))
),
fluidRow(
column(6,
wellPanel(h1("H")),
br(),
wellPanel(h1("I"))),
column(6,
wellPanel(h1("J")),
br(),
wellPanel(h1("K")))
)
)
}
})
}
shinyApp(ui = ui, server = server)

How to display content in nested tab menu structure (3 levels)?

In order to achieve a menu item, with two sub-levels, I wrote the code below. As you can see, the text in the subMenuItems is getting displayed properly. However, when the top level tab is selected, I want to display an empty page and on the second level (menuItem inside menuItem), I want to display the text "second".
What do I need to change, in order to get there?
# shiny lib
library(shiny)
library(shinythemes)
library(shinydashboard)
# UI
ui <- dashboardPage(
dashboardHeader(title = "Test"),
dashboardSidebar(
sidebarMenu(id = "tabs",
menuItem("Top_Level", tabName = "first",
icon = icon("chart-line"),
menuItem("Second_level",
tabName = "second",
menuSubItem("Summary",
tabName = "third1",
),
menuSubItem("Details",
tabName = "third2",
)
)
)
)
),
dashboardBody(
tabItems(
tabItem(tabName = "first",
mainPanel(width = 100,
fluidPage(fluidRow(
p("")
)
)
)
),
tabItem(tabName = "second",
mainPanel(width = 100,
fluidPage(fluidRow(
p("second")
)
)
)
),
tabItem(tabName = "third1",
mainPanel(width = 100,
fluidPage(fluidRow(
p("third.1")
)
)
)
),
tabItem(tabName = "third2",
mainPanel(width = 100,
fluidPage(fluidRow(
p("third.2")
)
)
)
)
)
)
)
# server
server <- function(input, output, session) {
renderText(output$first)
renderText(output$second)
renderText(output$third1)
renderText(output$third2)
}
runApp(list(ui = ui, server = server), launch.browser = TRUE)

How to make a tabitem to be rendered only after the user clicks it - shiny R

I´ve been looking for the solution to this but I do not find it
My issue is that I have a shiny dashboard that looks like this:
It is selecting all tabs even If I do not select them (like pre-rendered)
I tried making an observeEvent with a button but It do not know how to make the UI appear after they click it.
My code is
library(shiny)
library(shinydashboard)
gamestop <- tags$img(src = "GSLL.png",
height = '30', width = '170')
ui <- dashboardPage(skin = "yellow",
dashboardHeader(title = gamestop,
dropdownMenu(type = "tasks",
messageItem(
from = "My contact",
message = "x",
icon = icon("glyphicon glyphicon-envelope"),
href = "mailto:x"),
messageItem(
from = "Leads",
message = "y",
icon = icon("glyphicon glyphicon-envelope"),
href = "mailto:y"),
messageItem(
from = "",
message = "z",
icon = icon("glyphicon glyphicon-envelope"),
href = "mailto:z"),
icon = icon("envelope")
)
),
dashboardSidebar(
sidebarMenu(
menuItem("Main menu", tabName = "main_menu", icon = icon("home")),
menuItem("Peripherals", tabName = "peripherals", icon = icon("hdd")),
menuItem("Database repair", tabName = "widgets", icon = icon("th")),
menuItem("Polling", tabName = "polling", icon = icon("cloud")),
menuItem("more issues!!", tabName = "issues", icon = icon("ad"))
)
),
dashboardBody(tags$head(
tags$link(rel = "stylesheet", type = "text/css", href = "Custom.css")),
fluidPage(
tabItem(tabName = "peripherals",
h1("Peripherals",
style = "color:#15942B"),
tabsetPanel(type = "tabs",
tabPanel("Printers",br(),
tabsetPanel(type = "tabs",
tabPanel("M452DW",br(),
tabsetPanel(type = "tabs",
tabPanel("Not pinging"),
tabPanel("Error messages")
)
),
tabPanel("M402DW",br(),
tabsetPanel(type = "tabs",
tabPanel("Not pinging")
),
)
)
),
tabPanel("Pinpad",br(),
tabsetPanel(type = "tabs",
tabPanel("Offline / busy"),
tabPanel("Not turning on")
)
),
tabPanel("Scanners",br(),
tabsetPanel(type = "tabs",
tabPanel("GBT4400"),
tabPanel("DS2278")
)
),
tabPanel("Receipt printer / cashdrawer",br(),
tabsetPanel(type = "tabs",
tabPanel("Receipt printer"),
tabPanel("Cash drawer")
)
),
tabPanel("Label printer",br(),
tabsetPanel(type ="tabs",
tabPanel("ZD410"),
tabPanel("LP2824 & +")
),
)
)
), #Final tab peripherals
tabItem(tabName = "main_menu",
h1("Main menu",
style = "color:#15942B"),
strong("Here we can add the news of the day or a welcome image"),br(),
br(),
br(),
strong("This is a work in progress, to be presented to our team leads so we can make
it an aid page for all of us")
),
tabItem(tabName = "issues",
h1("More issue resolutions to come!!!!!",
style = "color:#15942B" ),
strong("My plan is to add the hardest issue resolutions for our team, so they can access this web page and
with a glipse they can resolve the issue in hand")
),
tabItem(tabName = "polling",
)
)
)
)
)
server <- function(input, output) {
observeEvent(input$tabs,
if(input$sidebarmenu == "Printers"){
})
}
shinyApp(ui, server)
I would like to know how to render the tab when the user clicks on the tab itself and not before
Thanks a lot!!!
If you want to render the tab when the user clicks on the tab, you need to observe the tabsetpanel and check if the tab is clicked.
library(shiny)
library(shinydashboard)
ui <- fluidPage(
tabItem(tabName = "peripherals",
h1("Peripherals",
style = "color:#15942B"),
tabsetPanel(id = "firsttabset",
type = "tabs",
tabPanel("Printers"),
tabPanel("Pinpad1",
h1("Dies ist tab \"Pinpad1\""),
textOutput("text")),
tabPanel("Scanners"),
tabPanel("Receipt printer / cashdrawer"),
tabPanel("Label printer")
)
)
)
server <- function(input, output) {
observeEvent(input$firsttabset, {
if(input$firsttabset == "Pinpad1") {
cat("tab \"Pinpad1\" is now being rendered \n")
output$text <- renderText({"tadaa"})
}
})
}
shinyApp(ui, server)
EDIT: If you want to apply this to nested tabsetpanels, I found a way by observing both tabsetpanel1 and tabsetpanel2 and checking in the conditions which tabs are selected. I suppose the first tab of tabsetpanel2, that is Scanners2 in this example, has to be rendered if you want to render the tab Pinpad1.
Check it out if it works for you. This logic can be extended to further nesting of tabsetpanels, but it will get complicated.
library(shiny)
library(shinydashboard)
ui <- fluidPage(
tabItem(tabName = "peripherals",
h1("Peripherals",
style = "color:#15942B"),
tabsetPanel(id = "firsttabset",
type = "tabs",
tabPanel("Printers"),
tabPanel("Pinpad1",
tabsetPanel(id = "secondtabset",
type = "tabs",
tabPanel("Scanners2",
h1("Dies ist tab \"Scanners2\"")),
tabPanel("Pinpad2",
h1("Dies ist tab \"Pinpad2\""),
textOutput("text2"))),
h1("Dies ist tab \"Pinpad1\""),
textOutput("text")),
tabPanel("Scanners"),
tabPanel("Receipt printer / cashdrawer"),
tabPanel("Label printer")
)
)
)
server <- function(input, output) {
observeEvent(c(input$firsttabset,
input$secondtabset), {
if(input$firsttabset == "Pinpad1" & input$secondtabset == "Scanners2") {
cat("tab \"Pinpad1\" is now being rendered \n")
output$text <- renderText({"tadaa"})
}
if (input$firsttabset == "Pinpad1" & input$secondtabset == "Pinpad2") {
cat("tab2 \"Pinpad2\" is now being rendered \n")
output$text2 <- renderText({"tadooo"})
}
})
}
shinyApp(ui, server)

How can I hide\show\toggle certain fields in R shiny modal based on other modal fields

I wish to have a popout modal within a shiny app that depending on the user's action within the modal,
it would show or hide certain fields.
For example, the Modal includes a button that when pressed, another button would apear\disappear.
sadly, although the observeEvent detects a change in the hide\show button, shinyjs::toggle(), shinyjs::hide()
and shinyjs::show() fail to work
example script:
library(shiny)
ui <- fluidPage(
actionButton("show_modal", "show modal"),
)
server <- function(input, output) {
observeEvent(input$show_modal, {
showModal(
modalDialog(footer = NULL,easyClose = T,
tagList(
fluidRow(
box(status = "primary", width = 6, style = "direction: ltr",
actionButton("toggle_btn", "show or hide second button")
)),
fluidRow(
box(status = "success", width = 6, style = "direction: ltr",
actionButton("box_btn", "Box!")
))
)
))
})
observeEvent(input$toggle_btn, {
shinyjs::toggle("box_btn")
cat("\npresentation button pressed\n")
})
}
shinyApp(ui, server)
You can do it without shinyjs by using conditionalPanel():
library(shiny)
ui <- fluidPage(
actionButton("show_modal", "show modal"),
)
server <- function(input, output) {
rv <- reactiveValues(show_btn = FALSE)
observeEvent(input$toggle_btn, {
rv$show_btn <- !rv$show_btn
})
output$show_btn <- reactive({rv$show_btn})
outputOptions(output, "show_btn", suspendWhenHidden = FALSE)
observeEvent(input$show_modal, {
# add_path_to_existing_offers_DB(user = user)
showModal(
modalDialog(
footer = NULL,
easyClose = T,
tagList(
fluidRow(
actionButton("toggle_btn", "show or hide second button")
),
conditionalPanel(
condition = "output.show_btn == true",
fluidRow(
actionButton("box_btn", "Box!")
)
)
)
)
)
})
}
shinyApp(ui, server)
Turns out as Dean Attali the author of shinyjs pointed out kindly,
that I failed to call useShinyjs() function.
library(shiny)
library(shinyjs)
ui <- fluidPage(
**useShinyjs(),**
actionButton("show_modal", "show modal"),
)
server <- function(input, output) {
observeEvent(input$show_modal, {
showModal(
modalDialog(footer = NULL,easyClose = T,
tagList(
fluidRow(
box(status = "primary", width = 6, style = "direction: ltr",
actionButton("toggle_btn", "show or hide second button")
)),
fluidRow(
box(status = "success", width = 6, style = "direction: ltr",
actionButton("box_btn", "Box!")
))
)
))
})
observeEvent(input$toggle_btn, {
shinyjs::toggle("box_btn")
cat("\npresentation button pressed\n")
})
}
shinyApp(ui, server)

Resources