Align three elements on Shiny dashboard - r

I try to put properly three elements on my Shiny dashboard
# User interface
ui <- fluidPage(theme = shinytheme("united"),
titlePanel("Crimes in Washington, DC (2017)"),
fluidRow(column(4,
selectInput("offenceInput", "Type of Offence",
choices =
sort(unique(incidents$OFFENSE)),
selected =
sort(unique(incidents$OFFENSE)),
multiple = TRUE),
selectInput("methodInput", "Method of Offence",
choices =
sort(unique(incidents$METHOD)),
selected =
sort(unique(incidents$METHOD)),
multiple = TRUE),
selectInput("shiftInput", "Police Shift",
choices =
sort(unique(incidents$SHIFT)),
selected =
sort(unique(incidents$SHIFT)),
multiple = TRUE),
selectInput('background', 'Background',
choices = providers,
multiple = FALSE,
selected = 'Stamen.TonerLite'),
dateRangeInput('dateRange',
label = 'Date',
start = as.Date('2017-01-01') ,
end = as.Date('2017-12-31')
)
),
column(10,
dataTableOutput('my_table'),
column(12,
leafletOutput(outputId = 'map', height = 600)
)
)
))
My map goes somewhere else, I tried different options. Just need map in a proper right top corner and a table below.

Here I have put all selectInput fields in left panel, map in right panel and my_table below these two panels. Trick is that column's 1st parameter should add to 12 (i.e. 4+8 in case of top panel and 12 in case of bottom panel).
ui <- fluidPage(fluidRow(column(4,
selectInput(...),
selectInput(...),
selectInput(...),
selectInput(...),
dateRangeInput(...)),
column(8,
leafletOutput(outputId = 'map', height = 600)),
column(12,
dataTableOutput('my_table'))))
Note: I was not able to test it due to lack of reproducible example but I hope this should work in your case.

Resolved with the help of RCommunity worldwide.
# User interface
ui <- fluidPage(theme = shinytheme("united"),
titlePanel(HTML("<h1><center><font size=14> Crimes in Washington, DC (2017) </font></center></h1>")),
fluidRow(column(4, align="center",
selectInput("offenceInput", "Type of Offence",
choices = sort(unique(incidents$Offense)),
selected = sort(unique(incidents$Offense)),
multiple = TRUE),
selectInput("methodInput", "Method of Offence",
choices = sort(unique(incidents$Method)),
selected = sort(unique(incidents$Method)),
multiple = TRUE),
selectInput("shiftInput", "Police Shift",
choices = sort(unique(incidents$Shift)),
selected = sort(unique(incidents$Shift)),
multiple = TRUE),
selectInput('background', 'Background',
choices = providers,
multiple = FALSE,
selected = 'Stamen.TonerLite'),
dateRangeInput('daterangeInput',
label = 'Date',
start = as.Date('2017-01-01') , end = as.Date('2017-12-31')
),
br(),
plotOutput("bar")
),
column(8,
leafletOutput(outputId = 'map', height = 600, width = 800),
dataTableOutput('my_table')
)
))
This gives the following layout. It is messy, but the structure is what I really wanted. Will improved small tweaks.

Related

R shiny: create variable in eventReactive that is used inside the defined function

I want to create a shny app that creates a interactive treemap.
The treemap should contain up to three layers, depending on user's choice.
The user can specify one, two or three layers, choosing from a dropdown list for each layer.
Hitting an actioButton, the map should be produced.
The ui part
ui <- fluidPage(
# Application title
navbarPage("Ist-Analyse Biodiversitätsmonitoring in Deutschland",
#####
tabPanel("Treemap", fluid = T,
sidebarLayout(
sidebarPanel(
radioButtons(inputId = "status",
label = "Programm - Status",
choices = c("Alle" = "Alle",
"laufend" = "laufend",
"in Erprobung" = "in Erprobung",
"in Entwicklung" = "in Entwicklung",
"beendet" = "beendet"),
selected = c("Alle")
),
br(),
selectInput(inputId = "level1",
label = "Ebene 1",
choices = Auswahl$Titel[Auswahl$use_treemaps == 1],
selected = Auswahl$Titel[Auswahl$use_treemaps == 1][1]),
br(),
selectInput(inputId = "level2",
label = "Ebene 2",
choices = Auswahl$Titel[Auswahl$use_treemaps == 1],
selected = c(''),
br(),
selectInput(inputId = "level3",
label = "Ebene 3",
choices = c('',
Auswahl$Titel[Auswahl$use_treemaps == 1]),
selected = c('')),
actionButton(inputId = "submit",
label = "Los!",
icon = icon("table")
)
),
mainPanel(
d3tree3Output(outputId = "treemap",
width = "100%",
height = "400px"),
)
)
)
)
)
The server part
server <- function(input, output) {
### determine, how many levels to drill down
## therefore, I bind together the selected levels (1 to 4) in tab "Treemap"
treemap_reactive <- eventReactive(input$submit, {
#####
drill_levels<- c(input$level1,
input$level2,
input$level3)
## then, depending on lenght(drill_levels), the treemaps
## are composed to the defined level of depth
drill_levels<- drill_levels[-c(which(drill_levels=''))]
treemap<-treemap(groups.1,
index=drill_levels,
vSize="value",
type="index",
na.rm=T,
draw=F)
d3tree3(treemap,
rootname = c("Treemap")
)
}
)
output$treemap <- renderD3tree3({
treemap_reactive()
}
)
}
# Run the application
shinyApp(ui = ui, server = server)
The group.1 datatset is the dataset containing the information to be visualized.
If I start the app, choose my levels (either one, two or tree) and hit the actionButton
I get an error "can't find object 'drill_levels'"
However, if I run the code with pre-defining 'drill_levels' in the R global envronment, the code works exactly as I expected.
So the problem seems to be that the variable 'drill_levels' is not created inside the eventReactive() function.
Does someone have an idea how to solve the issue?

Filters in Mainpanel Horizontally

I'm trying to build Rshiny app, i have 3 tabs, but my problem is in the first one, I have 2 filters for this page "Country" and "Package" and i want to show in the top of main panel both filters but horizontally, i mean, Package should be in the right part of Country filter, How can i modify my current code to show both filters in one line?, Thanks !!
shinyAppui <- tagList(
useShinyjs(),
navbarPage(
title = "Alternative Risk Transfer - Parametric Weather Solutions",
id = "navbar",
tabPanel(title="Map",
value= "_map",
sidebarLayout(
sidebarPanel( width = NULL, height = NULL
# Filter for country
# pickerInput(inputId = "country_", label = strong(" Select Country"),
# choices = unique(Stations_static$Country), "Labels",
# options = list(`live-search` = TRUE)),
#
# # Filter for package
# uiOutput("data_filtered_country")
#
),
mainPanel(
pickerInput(inputId = "country_", label = strong(" Select Country"),
choices = unique(Stations_static$Country), "Labels",
options = list(`live-search` = TRUE), inline = TRUE),
uiOutput("data_filtered_country"),
leafletOutput("map_stations",width="150%",height="550px"),
DT::DTOutput("table_map",width="150%",height="550px")
)),
fluidRow(
style = "border-top: 1px solid; border-color: #A9A9A9; padding-top: 10px;padding-bottom: 10px;",
column(width = 8),
column(width = 2),
column(
width = 2,
style = "padding-left: 0px;",
actionButton(
inputId = "showTabRiskQuantification",
label = "Static data updated as of June 2020",
width = '100%'
)
)
)
), # ends tab panel
As #YBS said in the comment when you want to place objects in the same row you should use the fluidRow(column(),column(),...) structure. This will make your dashboard responsive as well. In this case it would look like this.
fluidRow(
column(
width = 3,
pickerInput(inputId = "country_", label = strong(" Select Country"),
choices = unique(Stations_static$Country), "Labels",
options = list(`live-search` = TRUE), inline = TRUE)
),
column(
width = 3,
uiOutput("data_filtered_country")
)
)
where you can play around with different values for width to get the spacing you want.

Issue in inserting value with rhandsontable

Thanks for taking your valuable time to pitch in into this question. :-)
I'm building a shiny app that would take user inputs through rhandsontable and save it as a .rds file for data persistence.
The code is as follows:
Global.r
library(shiny)
library(shinydashboard)
library(shinycssloaders
library(rhandsontable)
library(htmltools)
library(plotly)
library(shinyjs)
library(tidyverse)
library(DT)
# Reads the data stored already
raw_data_projects <- readRDS("Projects.rds")
# code to refresh app so as to display the newly added data
jsResetCode <- "shinyjs.reset = function() {history.go(0)}"
ui.R
dashboardPage(skin = "black",
dashboardHeader(dropdownMenuOutput("dropdownmenu"),title = "PMO Dashboard",
tags$li(div(img(src = 'TechM_logo.png',
height = "35px"),
style = "padding-top:10px; padding-bottom:10px;"),
class = "dropdown"),dropdownMenuOutput("msgOutput")) ,
dashboardSidebar(
sidebarMenu(
menuItem("Home", tabName = "home", icon = icon("home")),
menuItem("Projects", tabName = "pros", icon = icon("briefcase")),
menuItem("About Team", tabName = "teamstr", icon = icon("user-friends")),
menuItem("Training & Skills",tabName = "skills",icon = icon("book"))
)),
dashboardBody(
useShinyjs(), # Include shinyjs in the UI
extendShinyjs(text = jsResetCode),
tags$link(rel = "stylesheet", type = "text/css", href = "style_2.css"),
tabItems(
tabItem(tabName = "pros",
fluidPage(tabBox(width = "500px",
tabPanel("Metrics",
fluidRow(
valueBoxOutput("Completed", width = 3),
valueBoxOutput("WIP", width = 3),
valueBoxOutput("Delayed", width = 3),
valueBoxOutput("OnHold", width = 3)
),
fluidRow(
box(plotlyOutput("Project_category"), width = 4,solidHeader = TRUE, status = "primary", title = "Project Category", collapsible = TRUE),
box(plotlyOutput("Project_status"), width = 8,solidHeader = TRUE, status = "primary", title = "Project Status", collapsible = TRUE),
box(plotlyOutput("Complexity"), width = 4,solidHeader = TRUE, status = "primary", title = "Project Complexity", collapsible = TRUE),
box(plotlyOutput("Audits"), width = 4,solidHeader = TRUE, status = "primary", title = "Audit Status", collapsible = TRUE)
)),
tabPanel("Data",
box(withSpinner(rHandsontableOutput("Projects")), width = 12),
actionButton("saveBtnProjects", "Save Projects", icon = icon("save")),
actionButton("BtnResetProjects", "Reset Filters", icon = icon("eraser")))))
)))
server.r
shinyServer(function(input, output, session){
dt_projects <- reactive({ raw_data_projects })
vals <- reactiveValues()
output$Projects <- renderRHandsontable({
rhandsontable(dt_projects(), readOnly = FALSE, search = TRUE, selectCallback = TRUE ) %>%
hot_cols(columnSorting = TRUE, manualColumnMove = TRUE, manualColumnResize = TRUE ) %>%
hot_table(highlightRow = TRUE, highlightCol = TRUE) %>%
#hot_col("PROJECT.STATUS", renderer = text_renderer, type = "autocomplete") %>%
hot_rows(fixedRowsTop = 1)
})
# on click of button the file will be saved to the working directory
observeEvent(input$saveBtnProjects,
#write.csv(hot_to_r(input$Projects), file = "./Data/project_tracker.csv",row.names = FALSE)
saveRDS(hot_to_r(input$Projects),"Projects.rds")
)
# refresh the page
observeEvent(input$saveBtnProjects, {js$reset()})
})
So when I run the app I get the table I desire as below:
As we can see, as I was inserting values to the first column, all the other columns greyed out and I couldn't insert any values into it. Please help me with this issue.
Also please suggest if my code will display the data reactively as soon as I save the data by pressing Save Projects button.
Thanks a ton in advance!!
P.S : I have included the server code only for the table considering the length of the question leaving the code of other tabs. But still this code is reproducible.

Error: Expected an object with class 'shiny.tag' when trying to output renderValueBox

New to R and R Shiny. My goal is to output the maximum value of a column by a valueBoxOutput, whilst the value is able to update when filters are changed by the user e.g Date etc. I am receiving Error: Expected an object with class 'shiny.tag' which I have no clue what it means and I cannot see why the code is wrong.
ui.R
library(shinythemes)
library(shiny)
library(plotly)
library(lubridate)
library(shinydashboard)
ui <- dashboardPage(skin = "black",
dashboardHeader(title = "Metric Tracker")
dashboardSidebar(
sidebarMenu(
menuItem("Dashboard", tabName = "Dashboard", icon = icon("city")),
dashboardBody(fluidRow(
tabItems(
tabItem(tabName = "Dashboard",
box(collapsible = TRUE, title = "All Brands",status = "info",solidHeader = TRUE, width = 8, plotlyOutput("valuePlot", height = "500px"), plotlyOutput("testplot", height = "500px")),
box(width = 4,title = "Inputs", solidHeader = TRUE, status = "warning", selectInput("value", "1st Value to Track:" , choices = c("Units_Ordered", "Buy_Box_Percentage", "Ordered_Product_Sales", "Session_Percentage","aov"), selected = "Ordered_Product_Sales", multiple = FALSE, selectize = TRUE),
selectInput("value2", "2nd Value to Track:" , choices = c("Units_Ordered", "Buy_Box_Percentage", "Ordered_Product_Sales", "Session_Percentage","aov"), selected = "Units_Ordered", multiple = FALSE, selectize = TRUE),
selectInput("marketplace", "Select Marketplace", choices = c("UK","DE","FR","IT","ES")),
sliderInput("date", "Date Range:", min = as.Date("2019-07-06","%Y-%m-%d"), max = as.Date("2019-10-26","%Y-%m-%d"), value = c(as.Date( "2019-07-06"),as.Date( "2019-10-26")),step = 7, timeFormat = "%Y-%m-%d")),
valueBoxOutput("max", width =3), valueBoxOutput("min", width = 3)
),
server ( I am only including relevant parts of my code so if you believe it maybe somewhere else that is distrputive let me know, but to know everything else works perfectly)
server <- function(input, output){
output$max <- renderValueBox({
maxsales <- filter(metricx2, Date >= input$date[1] & Date <= input$date[2] & Marketplace %in% input$marketplace)
maxsales1 <- max(maxsales$Ordered_Product_Sales)%>%
valueBox(value =maxsales1,subtitle = "Maximum Sales Value")
})
output$min <- renderValueBox({
valueBox(
value = min(metricx2$Ordered_Product_Sales),
subtitle = "Minimum Sales Value"
)
})
}
shinyApp(ui = ui, server = server)
metricx2 is the data frame that I want to pull from. The 'Min' part works but its not reactive to the inputs of the user. Moreover, R has sometimes prompted my to input a reactive function within the render. Yet this has not worked for me. As well as, R struggled to find Ordered_Product_Sales even though it is clearly there which is frustrating.
Hope someone can help and point out an obvious mistake I am probably making.
Thanks
Not sure you want the pipe at the end of this line:
maxsales1 <- max(maxsales$Ordered_Product_Sales)%>%
Your problem is possibly on this server line:
maxsales1 <- max(maxsales$Ordered_Product_Sales)%>% valueBox(value =maxsales1,subtitle = "Maximum Sales Value")
Remove the pipe %>% and it should work.
})

updateCheckBoxGroupInput in shiny based on selection of other checkboxes

My shiny application has multiple tabs. In one of the tabs I have plot output which I want to use to create reports in another tab. I have included a checkbox in the first tab for the user to select the output for reporting. In the second tab I am trying to update a check box group input based on the selection of the first tab. However I am getting only the first option selected.
The reproducible code is as follows: This is based on ifelse condition:
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")),
menuItem("MY MONTHLY REPORTS", tabName = "myweeklyrep", icon = shiny::icon("compass"))
)),
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%;")
),
box(
checkboxInput(inputId = "top15categoriestplinescheck", "Add to reports", value = FALSE),
width = 6, status = "info", title = "Top 15 categories",
div(plotlyOutput("top15categoriestplines"), style = "font-size:90%")
))),
tabItem(
tabName = "myweeklyrep",
fluidRow(
h4("AVAILABLE ANALYSIS", align = 'center'),br(),
column(width = 12,
list(tags$div(align = 'left',
class = 'multicol',
checkboxGroupInput(inputId = 'analysisSelector',
label = "Select the analysis:",
choices = "",
selected = "",
inline = FALSE)))
))))))
server <- function(session,input,output){
observe({
updateCheckboxGroupInput(session, inputId = "analysisSelector", label = "", choices =
ifelse(!is.null(input$top15categoriestplinescheck) || length(input$top15categoriestplinescheck) != 0, "Inventory top 8 metros",
ifelse(!is.null(input$inventorytop8metrocheck) || length(input$inventorytop8metrocheck) != 0, "Top 15 categories - Topline", "No selection")),
selected = "",inline = FALSE)
})
}
shinyApp(ui,server)
I tried with if, else if also but they aren't working. Any thoughts?
The if, else if conditions:
updateCheckboxGroupInput(session, inputId = "analysisSelector", label = "", choices =
if(!is.null(input$top15categoriestplinescheck) || length(input$top15categoriestplinescheck) != 0){
"Inventory top 8 metros"
} else if (!is.null(input$inventorytop8metrocheck) || length(input$inventorytop8metrocheck) != 0){
"Top 15 categories - Topline"
} else {
return()
},
selected = "",inline = FALSE)
EDIT:
I tried the following option: which renders the checkboxes irrespective of whether they are selected or not.
getlist <- reactive({
if(!is.null(input$top15categoriestplinescheck) & !is.null(input$inventorytop8metrocheck)){
c("Top 15 categories - Topline","Inventory of top 8 metros - Topline")
} else if (!is.null(input$top15categoriestplinescheck)){
"ABC"
} else if (!is.null(input$inventorytop8metrocheck)){
"DEF"
} else {
return()
}
})
observe({
updateCheckboxGroupInput(session, inputId = "analysisSelector", label = "Select the analysis:", choices =
as.list(getlist()),
selected = "",inline = FALSE)
})
This is actually easier to handle with observeEvent as explained in the documentation of this function (see ?observeEvent). From what I understand, it actually wraps observe but in a more intuitive way.
You have to pass it two arguments: an event (in this case, the click on one of your checkboxGroupInputs) and the action to perform when this event occurs.
The server function thus becomes:
server <- function(session,input,output){
updateAnalysisSelector <- function(session) {
choices <- ifelse(input$top15categoriestplinescheck, "Inventory top 8 metros",
ifelse(input$inventorytop8metrocheck, "Top 15 categories - Topline", "No selection"))
updateCheckboxGroupInput(session,
inputId = "analysisSelector",
label = "Select the analysis:",
choices = choices,
selected = "",
inline = FALSE)
}
observeEvent(input$top15categoriestplinescheck, updateAnalysisSelector(session))
observeEvent(input$inventorytop8metrocheck, updateAnalysisSelector(session))
}
I'm sure this could be simplified if your UI did not have two separate checkbox groups but this works for your current implementation.

Resources