Related
In my Shiny app, I want to include a selectInput in a DT datatable and allow selection of multiple options. This renders fine with multiple = F, but with multiple = T, the selection doesn't display or work properly. Please see example below. When "Multiple" is unselected, the selectInput renders fine in the table, but when it is selected, the selectInput is not rendered properly. Any suggestions?
Update: I modified the code to include a selectInput by itself with multiple = TRUE to show what I expect it to look like in the table. Specifically, in the table, there is no field above the dropdown with the selections displayed and I am unable to select multiple choices. Also see screenshot.
require(shiny)
require(DT)
shinyApp(
ui = fluidPage(
checkboxInput(inputId = "multiple", label = "Multiple", value = F),
selectInput(inputId = "expected", label = "Expected", choices = letters, multiple = T),
DT::dataTableOutput("mytable")
),
server = function(input, output, session) {
output$mytable <- DT::renderDataTable({
if(is.null(input$multiple)) return()
DT::datatable(
data = data.frame(
Col1 = c(
as.character(selectInput(
inputId = "id1",
label = NULL,
choices = letters,
multiple = input$multiple
))
)
),
escape = F,
selection = "none"
)
})
}
)
Update 2:
Thanks to #Jamie for a great solution. I was able to modify that solution when I need multiple selectInputs in my table and want the same desired format. See below:
require(shiny)
require(DT)
SelectizeIDs <- function(ids) {
myStrings <- as.character(sapply(ids, function(id) {
paste0(" $('#", id, "').selectize();")
}))
c(
"function(settings){",
myStrings,
"}"
)
}
shinyApp(
ui = fluidPage(
checkboxInput(inputId = "multiple", label = "Multiple", value = F),
selectInput(inputId = "expected", label = "Expected", choices = letters, multiple = T),
DT::dataTableOutput("mytable")
),
server = function(input, output, session) {
output$mytable <- DT::renderDataTable({
DT::datatable(
data = data.frame(
Col1 = c(
as.character(selectInput(
inputId = "id1",
label = NULL,
choices = letters,
multiple = input$multiple
)),
as.character(selectInput(
inputId = "id2",
label = NULL,
choices = letters,
multiple = input$multiple
))
)
),
escape = F,
selection = "none",
options = list(
ordering = F,
initComplete = JS(SelectizeIDs(c("id1", "id2"))),
preDrawCallback = JS('function(){Shiny.unbindAll(this.api().table().node());}'),
drawCallback = JS('function(){Shiny.bindAll(this.api().table().node());}')
)
)
})
}
)
Here's an option where I leaned heavily from this question.
SelectizeInput inside DT::datatable only works as html
Which leans on this question. Shiny widgets in DT Table
Since your data data.frame has the appropriate html already set up. You need to make sure that selectize is added to the id in this case id1. From inspecting element on your expected vs actual input, it looks like all the selectize JS is being excluded
js <- c(
"function(settings){",
" $('#id1').selectize()",
"}"
)
Then in the options initialize the js function above and and bind the inputs.
shinyApp(
ui = fluidPage(
checkboxInput(inputId = "multiple", label = "Multiple", value = F),
selectInput(inputId = "expected", label = "Expected", choices = letters, multiple = T),
DT::dataTableOutput("mytable")
),
server = function(input, output, session) {
output$mytable <- DT::renderDataTable({
# if(is.null(input$multiple)) return()
DT::datatable(
data = data.frame(
Col1 = c(
as.character(selectInput(
inputId = "id1",
label = NULL,
choices = letters,
multiple = input$multiple
))
)
),
escape = F,
selection = "none",
options = list(
initComplete = JS(js),
preDrawCallback = JS('function(){Shiny.unbindAll(this.api().table().node());}'),
drawCallback = JS('function(){Shiny.bindAll(this.api().table().node());}')
)
)
})
}
)
Im new to R shiny and have ran into a weird issue. Im using a selectizeGroupUI function to have some filter inputs in the UI. for some reason one of my filter options always lines up oddly. Ive attached the code from my UI below along with a screenshot of the actual output. any help would be greatly appreciated.
ui <- fluidPage(theme = shinytheme("cerulean"),
titlePanel(h1("Powered")),
sidebarLayout(
sidebarPanel(
fluidRow(
checkboxGroupInput(
inputId = "vars",
label = h3("Filters:"),
choices = c("Program", "Site", "Buyer", "Part_Number"),
selected = c("Program", "Site", "Buyer", "Part_Number")
),
panel(
column(
width = 8,
selectizeGroupUI(
id = "my-filters",
params = list(
Program = list(inputId = "Program", label = h5("Program:")),
Buyer = list(inputId = "Buyer", label = h5("Buyer:")),
Site = list(inputId = "Site", label = h5("Site:")),
#Buyer = list(inputId = "Buyer", title = "Buyer:"),
Part_Number = list(inputId = "Part_Number", label = h5("Part Number:"))
), inline = FALSE
))),
status = "primary"),
fluidRow(
selectInput("select1","Part Tracker", choices = unique(mydataTS$Part_Number))
),
fluidRow(
tags$image(src = "B.png",height= "30%" , width= "30%" ,align = "left"),
tags$image(src = "A.png",height= "30%" , width= "30%" ,align = "right")
),
width = 4 ),
)
Also here is the server side
mydataTS1 <-excel_sheets("~/Desktop/Updated-Dashboard-code3:15/Prototype v5/Dashboard-TSData4.xlsx") %>% map_df(~read_xlsx("~/Desktop/Updated-Dashboard-code3:15/Prototype v5/Dashboard-TSData4.xlsx",.))
shinyServer(
function(input, output, session) {
vars_r <- reactive({input$vars})
res_mod <- callModule(module = selectizeGroupServer,id = "my-filters", data = mydataTS1, vars = vars_r, inline = FALSE)
print(res_mod)
output$table <- DT::renderDataTable({
req(res_mod())
res_mod()
})
OUTPUT OF UI
My apologies for the bad first question, I'm new to SO but learning.
Let me know if any other information is required.
I am able to render a datatable in my shiny app. However, whenever there is a wide table, the horizontal scroller gets back to it's initial position when you apply filters on the columns in the back. This issue occurs with numeric columns only.
I was wondering if there is a way I can disable range-based filters (but keep the filters itself) or if there is any other workaround for this problem.
I have searched github issues and stackoveflow prior to posting this question here since I couldn't find anybody having this problem.
Here is a reproducible example along with pictures-
options(scipen = 99999) #converts the sci numbers to their regular format
library(shiny)
library(shinyjs)
library(shinyWidgets)
library(shinythemes)
library(writexl)
library(dplyr)
library(DT)
library(dplyr)
mtcars_modified <- mtcars %>% dplyr::mutate(wt_2= wt,
qsec_2 = qsec,
am_2= am,
mpg_2= mpg,
gear_2 = gear,
carb_2 = carb,
disp_2 = disp,
row_names_col= rownames(mtcars))
ui <- fluidPage(
theme = shinythemes::shinytheme("simplex"),
shinyjs::useShinyjs(), # enables javascript/jQuery enhanchments
# Create Right Side Text
navbarPage(
id = "navbar",
title= div(HTML("G<em>T</em>")),
#windowTitle = "GT",
tabPanel("Data Set Info",
materialSwitch(inputId = "toggleSidebar", label = "Toggle Panel: ",
value = TRUE, status = "warning"),
sidebarLayout(
# radio/action buttons
sidebarPanel(
id = "Sidebar",
prettyRadioButtons(
inputId = "controller",
label = "Choose:",
choices = c("About"= 1,
"iris"= 2,
"mtcars_modified" = 3),
icon= icon("check"),
selected = 1,
status = "success",
animation="smooth"
),
br(),
br()
),
#panel where output is shown from server
mainPanel(
id = "main_panel",
tabsetPanel(
id = "hidden_tabs",
type = "hidden",
tabPanelBody(
"panel1", "navigation"
),
tabPanelBody(
"panel2",
tabsetPanel(
tabPanel("Data", DT::DTOutput('panel1_data')),
tabPanel("Summary", verbatimTextOutput("panel1_sum")),
tabPanel(
"Plot"
)
)
),
tabPanelBody(
"panel3",
tabsetPanel(
tabPanel("Data", DT::DTOutput('panel3_data')),
tabPanel("Summary", verbatimTextOutput("panel3_sum")),
tabPanel(
"Plot"
)
)
)
)
)
)
) ,
#resizes the navbar tabs/button
tags$head(tags$style(HTML('.navbar-brand {width: 270px; font-size:35px; text-align:left;
font-family: "serif";')))
)
)
server <- function(input, output, session) {
# this event hides the side panel when toggled on/off
observeEvent(input$toggleSidebar, {
shinyjs::toggle(id = "Sidebar", condition = input$toggleSidebar)
if(!isTRUE(input$toggleSidebar)) {
shinyjs::runjs("$('#main_panel').removeClass('col-sm-8').addClass('col-sm-12')")
} else {
shinyjs::runjs("$('#main_panel').removeClass('col-sm-12').addClass('col-sm-8')")
}
})
# here we put all the data
data_sets <- list(df1 = data.frame(),
df2= iris,
df3 = mtcars_modified)
# store current dataset in reactive so we can work with plot panels
data_to_use <- reactiveValues(name = "df", data = data.frame())
observeEvent(input$controller, {
# skip first panel since it is used to display navigation
updateTabsetPanel(session, inputId= "hidden_tabs", selected = paste0("panel", input$controller))
# enswure value is avilable throught selected tabSet
req(input$controller)
# get current data and df name
data_to_use$data <- data_sets[[as.numeric(input$controller)]]
data_to_use$name <- names(data_sets[as.numeric(input$controller)])
# update table and sum
output[[paste0('panel', input$controller, '_data')]] <-
DT::renderDT(server = FALSE, {
DT::datatable(data_to_use$data,
filter = 'top',
extensions = 'Buttons',
options = list(scrollY = 600,
scrollX = TRUE,
dom = '<"float-left"l><"float-right"f>rt<"row"<"col-sm-4"B><"col-sm-4"i><"col-sm-4"p>>',
lengthMenu= list(c(10, 25, 50, -1),
c('10', '25', '50','All')),
buttons = list(
list(extend = "collection", text = "Download",
filename = "data_excel",
exportOptions = list(
modifier = list(page = "all")
),
action = DT::JS("function ( e, dt, node, config ) {
Shiny.setInputValue('Download_DATA', true, {priority: 'event'});}"
)
)
),
scrollCollapse= TRUE,
lengthChange = TRUE,
widthChange= TRUE,
rownames = TRUE))})
output[[paste0('panel', input$controller, '_sum')]] <- renderPrint(summary(data_to_use$data))
})
}
#runs the app
shinyApp(ui= ui, server= server)
I have some requests for my app.
{1} After readjusting the mainPanel, esquisserUI filters are not popping up anymore. Here is the working example which I followed https://dreamrs.github.io/esquisse/articles/shiny-usage.html
In addition, I also looked at this GitHub issue, however it was for disabling the filters: https://github.com/dreamRs/esquisse/issues/71
And final request regarding general information:
{2} what does server = FALSE will do for huge datasets? (https://rstudio.github.io/DT/server.html) DT recommends to leave it as default to TRUE state, however if I do that, I don't get the full data upon download. I only get the data in the current page. Are there problems you foresee?
Thank you, here is a reproducible example.
library(shiny)
library(shinyjs)
library(shinyWidgets)
library(esquisse)
library(shinythemes)
library(xlsx)
library(DT)
# Credit: #Iz100 helped me a lot with UI.
ui <- fluidPage(
theme = shinytheme("simplex"),
useShinyjs(),
# Create Right Side Text
navbarPage(
title= div(HTML("G<em>T</em>")),
tabPanel("Data Set Info",
materialSwitch(inputId = "toggleSidebar", label = "Toggle Panel: ",
value = TRUE, status = "warning"),
sidebarLayout(
# radio/action buttons
sidebarPanel(
id = "Sidebar",
prettyRadioButtons(
inputId = "controller",
label = "Choose:",
choices = c("About"= 1,
"iris"= 2,
"mtcars" = 3),
icon= icon("check"),
selected = 1,
status = "success",
animation="smooth"
),
br(),
br(),
a(actionButton(inputId = "admin_email", label = "Contact Admin",
icon = icon("envelope", lib = "font-awesome")),
href="mailto:my_awesome_email_address.com")
),
#panel where output is shown from server
mainPanel(
id = "main_panel",
tabsetPanel(
id = "hidden_tabs",
type = "hidden",
tabPanelBody(
"panel1", "navigation"
),
tabPanelBody(
"panel2",
tabsetPanel(
tabPanel("Data", DT::DTOutput('panel1_data')),
tabPanel("Summary", verbatimTextOutput("panel1_sum")),
tabPanel(
"Plot",
esquisserUI(
id = "esquisse2",
header = FALSE,
choose_data = FALSE
)
)
)
),
tabPanelBody(
"panel3",
tabsetPanel(
tabPanel("Data", DT::DTOutput('panel3_data')),
tabPanel("Summary", verbatimTextOutput("panel3_sum")),
tabPanel(
"Plot",
esquisserUI(
id = "esquisse3",
header = FALSE,
choose_data = FALSE
)
)
)
)
)
)
)
) ,
#resizes the navbar tabs/button
tags$head(tags$style(HTML('.navbar-brand {width: 270px; font-size:35px; text-align:left;}')))
)
)
server <- function(input, output, session) {
# this event hides the side panel when toggled on/off
observeEvent(input$toggleSidebar, {
shinyjs::toggle(id = "Sidebar", condition = input$toggleSidebar)
if(!isTRUE(input$toggleSidebar)) {
shinyjs::runjs("$('#main_panel').removeClass('col-sm-8').addClass('col-sm-12')")
} else {
shinyjs::runjs("$('#main_panel').removeClass('col-sm-12').addClass('col-sm-8')")
}
})
myModal <- function() {
div(id = "Download_DATA",
modalDialog(easyClose = TRUE,
title = "Alert!",
"Please remove all the filters if you want a full dataset.",
br(),
br(),
downloadButton("download_excel","Download as XLSX")
)
)
}
# here we put all the data
data_sets <- list(df1 = data.frame(),
df2= iris,
df3 = mtcars)
# store current dataset in reactive so we can work with plot panels
data_to_use <- reactiveValues(name = "df", data = data.frame())
# modules only need to be called it once but individually for esquisse
callModule(
module = esquisserServer,
id = "esquisse2",
data = data_to_use
)
callModule(
module = esquisserServer,
id = "esquisse3",
data = data_to_use
)
observeEvent(input$controller, {
# skip first panel since it is used to display navigation
updateTabsetPanel(session, inputId= "hidden_tabs", selected = paste0("panel", input$controller))
# enswure value is avilable throught selected tabSet
req(input$controller)
# get current data and df name
data_to_use$data <- data_sets[[as.numeric(input$controller)]]
data_to_use$name <- names(data_sets[as.numeric(input$controller)])
# update table and sum
output[[paste0('panel', input$controller, '_data')]] <- DT::renderDT(server = FALSE, {
DT::datatable(data_to_use$data,
filter = 'top',
extensions = 'Buttons',
options = list(scrollY = 600,
scrollX = TRUE,
dom = '<"float-left"l><"float-right"f>rt<"row"<"col-sm-4"B><"col-sm-4"i><"col-sm-4"p>>',
lengthMenu= list(c(10, 25, 50, -1),
c('10', '25', '50','All')),
buttons = list(
list(extend = "collection", text = "Download",
filename = "data_excel",
exportOptions = list(
modifier = list(page = "all")
),
action = DT::JS("function ( e, dt, node, config ) {
Shiny.setInputValue('Download_DATA', true, {priority: 'event'});}"
)
)
),
scrollCollapse= TRUE,
lengthChange = TRUE,
widthChange= TRUE,
rownames = TRUE))})
output[[paste0('panel', input$controller, '_sum')]] <- renderPrint(summary(data_to_use$data))
})
# observes if download is clicked
observeEvent(input$Download_DATA, {
showModal(myModal())
})
# writes to an excel file
output$download_excel <- downloadHandler(
filename = function() {
paste("data-", Sys.Date(), ".xlsx", sep="")
},
content = function(file) {
write.xlsx(data_to_use$data, file, row.names = FALSE)
}
)
}
#runs the app
shinyApp(ui= ui, server= server)
1. I checked the HTML of esquisserUI, they give all dropdowns the same IDs if you use multiple esquisserUI. This is a big NO in HTML development and will cause a lot of issues. They call it a module, but they didn't follow Shiny module guidelines where to use NS() for all UI IDs. The easy proof is try this below. Then uncomment the second set of esquisserUI and esquisserServer and try again. You will find the dropdown no longer works.
library(esquisse)
ui <- fluidPage(
esquisserUI(
id = "esquisse1",
header = FALSE,
choose_data = FALSE
)#,
# esquisserUI(
# id = "esquisse2",
# header = FALSE,
# choose_data = FALSE
# )
)
server <- function(input, output, session) {
data_to_use <- reactiveValues(data = iris, name = "iris")
callModule(
module = esquisserServer,
id = "esquisse1",
data = data_to_use
)
# callModule(
# module = esquisserServer,
# id = "esquisse2",
# data = data_to_use
# )
}
shinyApp(ui, server)
Currently there is no straight fix for this unless you ask them to fix it. We need to use a workaround:
I added a new tab to the main panel called "plot" which is the esquisserUI, and two buttons in the data panel so when you click on the button, it will jump you to the plot panel with the right data.
library(shiny)
library(shinyjs)
library(shinyWidgets)
library(esquisse)
library(shinythemes)
library(xlsx)
library(DT)
# Credit: #Iz100 helped me a lot with UI.
ns <- NS("myapp")
ui <- fluidPage(
theme = shinytheme("simplex"),
useShinyjs(),
# Create Right Side Text
navbarPage(
title= div(HTML("G<em>T</em>")),
tabPanel("Data Set Info",
materialSwitch(inputId = "toggleSidebar", label = "Toggle Panel: ",
value = TRUE, status = "warning"),
sidebarLayout(
# radio/action buttons
sidebarPanel(
id = "Sidebar",
prettyRadioButtons(
inputId = "controller",
label = "Choose:",
choices = c("About"= 1,
"iris"= 2,
"mtcars" = 3,
"plots" = 4),
icon= icon("check"),
selected = 1,
status = "success",
animation="smooth"
),
br(),
br(),
a(actionButton(inputId = "admin_email", label = "Contact Admin",
icon = icon("envelope", lib = "font-awesome")),
href="mailto:my_awesome_email_address.com")
),
#panel where output is shown from server
mainPanel(
id = "main_panel",
tabsetPanel(
id = "hidden_tabs",
type = "hidden",
tabPanelBody(
"panel1", "navigation"
),
tabPanelBody(
"panel2",
tabsetPanel(
tabPanel(
"Data", DT::DTOutput('panel2_data'),
actionButton("plot2", "Plot iris")
),
tabPanel("Summary", verbatimTextOutput("panel2_sum"))
)
),
tabPanelBody(
"panel3",
tabsetPanel(
tabPanel(
"Data", DT::DTOutput('panel3_data'),
actionButton("plot3", "Plot mtcars")
),
tabPanel("Summary", verbatimTextOutput("panel3_sum"))
)
),
tabPanelBody(
"panel4",
esquisserUI(
id = "esquisse",
header = FALSE,
choose_data = FALSE
)
)
)
)
)
),
#resizes the navbar tabs/button
tags$head(tags$style(HTML('.navbar-brand {width: 270px; font-size:35px; text-align:left;}')))
)
)
server <- function(input, output, session) {
# this event hides the side panel when toggled on/off
observeEvent(input$toggleSidebar, {
shinyjs::toggle(id = "Sidebar", condition = input$toggleSidebar)
if(!isTRUE(input$toggleSidebar)) {
shinyjs::runjs("$('#main_panel').removeClass('col-sm-8').addClass('col-sm-12')")
} else {
shinyjs::runjs("$('#main_panel').removeClass('col-sm-12').addClass('col-sm-8')")
}
})
myModal <- function() {
div(id = "Download_DATA",
modalDialog(easyClose = TRUE,
title = "Alert!",
"Please remove all the filters if you want a full dataset.",
br(),
br(),
downloadButton("download_excel","Download as XLSX")
)
)
}
# here we put all the data
data_sets <- list(df1 = data.frame(),
df2= iris,
df3 = mtcars)
# store current dataset in reactive so we can work with plot panels
data_to_use <- reactiveValues(name = "df", data = data.frame())
# modules only need to be called it once but individually for esquisse
callModule(
module = esquisserServer,
id = "esquisse",
data = data_to_use
)
# go to plot panel if plot button clicked
observeEvent(c(input$plot2, input$plot3), {
updatePrettyRadioButtons(session, "controller", selected = 4)
}, ignoreInit = TRUE)
observeEvent(input$controller, {
# skip first panel since it is used to display navigation
updateTabsetPanel(session, inputId= "hidden_tabs", selected = paste0("panel", input$controller))
# enswure value is avilable throught selected tabSet
# only render data if data panels are selected
req(input$controller %in% 2:3)
# get current data and df name
data_to_use$data <- data_sets[[as.numeric(input$controller)]]
data_to_use$name <- names(data_sets[as.numeric(input$controller)])
# update table and sum
output[[paste0('panel', input$controller, '_data')]] <- DT::renderDT(server = FALSE, {
DT::datatable(data_to_use$data,
filter = 'top',
extensions = 'Buttons',
options = list(scrollY = 600,
scrollX = TRUE,
dom = '<"float-left"l><"float-right"f>rt<"row"<"col-sm-4"B><"col-sm-4"i><"col-sm-4"p>>',
lengthMenu= list(c(10, 25, 50, -1),
c('10', '25', '50','All')),
buttons = list(
list(extend = "collection", text = "Download",
filename = "data_excel",
exportOptions = list(
modifier = list(page = "all")
),
action = DT::JS("function ( e, dt, node, config ) {
Shiny.setInputValue('Download_DATA', true, {priority: 'event'});}"
)
)
),
scrollCollapse= TRUE,
lengthChange = TRUE,
widthChange= TRUE,
rownames = TRUE))})
output[[paste0('panel', input$controller, '_sum')]] <- renderPrint(summary(data_to_use$data))
})
# observes if download is clicked
observeEvent(input$Download_DATA, {
showModal(myModal())
})
# writes to an excel file
output$download_excel <- downloadHandler(
filename = function() {
paste("data-", Sys.Date(), ".xlsx", sep="")
},
content = function(file) {
write.xlsx(data_to_use$data, file, row.names = FALSE)
}
)
}
#runs the app
shinyApp(ui= ui, server= server)
2. So server = TRUE only sends a very small portion of the entire dataset to UI for large ones. When you scroll or jump pages, new data will be sent. This saves time and has better performance. If it is FALSE, all data will be sent at once. Imagine you need to load a 2GB table in your browser everytime you start the app, how slow will it be. For small datasets, you can leave it FALSE.
Updates
It seems esquisse people fixed the bug. Install the develop version and then:
ui <- fluidPage(
esquisse_ui(
id = "esquisse1",
header = FALSE
),
esquisse_ui(
id = "esquisse2",
header = FALSE
)
)
server <- function(input, output, session) {
data_to_use <- reactiveValues(data = iris, name = "iris")
esquisse_server(id = "esquisse1", data_rv = data_to_use)
esquisse_server(id = "esquisse2", data_rv = data_to_use)
}
shinyApp(ui, server)
I have a reproducible example below where only the first tabPanel is working, however when I switch to another panel, I don't get any renders (the toggle becomes un-interactable also). I have looked into conditionalPanel however I see them getting done without the use of mainPanel I was wondering if it possible to have tabs where each tab has its own mainPanel , so I can see a different sidebar and an output contained within different tabs. Any help is welcome!
options(scipen = 99999) #converts the sci numbers to their regular format
library(shiny)
library(shinyjs)
library(shinyWidgets)
library(shinyalert)
library(esquisse)
library(DT)
library(dplyr)
#library(devtools)
#library(remotes)
#remotes::install_github("dreamRs/esquisse")
library(hrbrthemes)
library(ggthemes)
library(ggplot2)
library(svglite)
ui <- fluidPage(
shinyjs::useShinyjs(), # enables javascript/jQuery enhanchments
# Create Right Side Text
navbarPage(
title= div(HTML("G<em>T</em>")),
#General reports
tabPanel("General Reports",
shinyWidgets::materialSwitch(inputId = "toggleSidebar", label = "Toggle Panel: ",
value = TRUE, status = "warning"),
sidebarLayout(
# radio/action buttons
sidebarPanel(
id = "Sidebar",
shinyWidgets::prettyRadioButtons(
inputId = "controller",
label = "Choose:",
choices = c("About"= 1,
"iris"= 2),
icon= icon("check"),
selected = 1,
status = "success",
animation="smooth"
),
br(),
br(),
a(actionButton(inputId = "admin_email", label = "Contact",
icon = icon("envelope", lib = "font-awesome")),
href="mailto:xyz#email.us")
),
#panel where output is shown from server
mainPanel(
id = "main_panel",
tabsetPanel(
id = "hidden_tabs",
type = "hidden",
tabPanelBody(
"panel1", "Text coming soon."
),
tabPanelBody(
"panel2",
tabsetPanel(
tabPanel("Data", DT::DTOutput('panel2_data')),
tabPanel(
"DIY Plot",
esquisse::esquisse_ui(
id = "esquisse2",
header = FALSE,
container = esquisseContainer(
width = "100%", height = "760px", fixed = FALSE
),
controls = c("labs", "parameters", "appearance", "filters", "code")
)
)
)
)
)
)
)
),
# monthly reports
tabPanel("Extra General Reports",
shinyWidgets::materialSwitch(inputId = "toggleSidebar", label = "Toggle Panel: ",
value = TRUE, status = "warning"),
sidebarLayout(
# radio/action buttons
sidebarPanel(
id = "Sidebar",
shinyWidgets::prettyRadioButtons(
inputId = "controller",
label = "Choose:",
choices = c("About"= 3,
"mtcars"= 4),
icon= icon("check"),
selected = 3,
status = "success",
animation="smooth"
),
br(),
br(),
a(actionButton(inputId = "admin_email", label = "Contact",
icon = icon("envelope", lib = "font-awesome")),
href="mailto:xyz#email.us")
),
#panel where output is shown from server
mainPanel(
id = "main_panel",
tabsetPanel(
id = "hidden_tabs",
type = "hidden",
tabPanelBody(
"panel3", "Text coming soon."
),
tabPanelBody(
"panel4",
tabsetPanel(
tabPanel("Data", DT::DTOutput('panel4_data')),
tabPanel(
"DIY Plot",
esquisse::esquisse_ui(
id = "esquisse4",
header = FALSE,
container = esquisseContainer(
width = "100%", height = "760px", fixed = FALSE
),
controls = c("labs", "parameters", "appearance", "filters", "code")
)
)
)
)
)
)
)
),
#resizes the navbar tabs/button
tags$head(tags$style(HTML('.navbar-brand {width: 270px; font-size:35px; text-align:left;
font-family: "serif";')))
)
)
server <- function(input, output, session) {
# this event hides the side panel when toggled on/off
observeEvent(input$toggleSidebar, {
shinyjs::toggle(id = "Sidebar", condition = input$toggleSidebar)
if(!isTRUE(input$toggleSidebar)) {
shinyjs::runjs("$('#main_panel').removeClass('col-sm-8').addClass('col-sm-12')")
} else {
shinyjs::runjs("$('#main_panel').removeClass('col-sm-12').addClass('col-sm-8')")
}
})
# here we put all the data
data_sets <- list(df1 = data.frame(),
df2 = iris,
df3 = data.frame(),
df4 = mtcars)
# store current dataset in reactive so we can work with plot panels
data_to_use <- reactiveValues(name = "df", data = data.frame())
# modules only need to be called it once but individually for esquisse
esquisse::esquisse_server(id = "esquisse2", data_rv = data_to_use)
esquisse::esquisse_server(id = "esquisse4", data_rv = data_to_use)
observeEvent(input$controller, {
# skip first panel since it is used to display navigation
updateTabsetPanel(session, inputId= "hidden_tabs", selected = paste0("panel", input$controller))
# enswure value is avilable throught selected tabSet
req(input$controller)
# get current data and df name
data_to_use$data <- data_sets[[as.numeric(input$controller)]]
data_to_use$name <- names(data_sets[as.numeric(input$controller)])
# update table and sum. Use server = FALSE to get full table
output[[paste0('panel', input$controller, '_data')]] <- DT::renderDT(server = FALSE, {
DT::datatable(data_to_use$data,
filter = 'top',
extensions = 'Buttons')})
})
}
#runs the app
shinyApp(ui= ui, server= server)
You have two radioButtons, one for each sidebar, but both of them have the inputId = "controller". Same with inputId = "toggleSidebar". InputIds need to be unique in shiny!
I suggest you either use a single sidebar for the entire app, or since both tabs are essentially identical you can also use modules.