Related
I have a Shiny app that collects Heights and Weights using the interface from the shiny app.
What I would like to have, is a table just below the raw value table that gives me an average of the heights and weights that were inputed into the app, and changes as rows are entered or deleted.
I tried to add some code to the replaceData function but that throws an error.
library(shiny)
library(tidyverse)
library(DT)
df <- dplyr::tibble(Height = numeric(), Weight = numeric())
ui <- fluidPage(
# App title ----
titlePanel("DT + Proxy + Replace Data"),
# Sidebar layout with input and output definitions ----
sidebarLayout(
# Sidebar panel for inputs ----
sidebarPanel(
# Input: Slider for the number of bins ----
shiny::textInput(inputId = "height", label = "height"),
shiny::textInput(inputId = "weight", label = "weight"),
shiny::actionButton(inputId = "add", label = "Add"),
shiny::selectInput(inputId = "remove_row", label = "Remove Row",
choices = 1:nrow(df)),
shiny::actionButton(inputId = "remove", label = "Remove")
),
# Main panel for displaying outputs ----
mainPanel(
# Output: Histogram ----
DT::DTOutput(outputId = "table"),
DT::DTOutput(outputId = "mean_table"),
)
)
)
# Define server logic required to draw a histogram ----
server <- function(input, output, session) {
mod_df <- shiny::reactiveValues(x = df)
output$table <- DT::renderDT({
mod_df$x
})
#table 2
output$mean_table <- DT::renderDT({
mod_df$x
})
shiny::observe({
shiny::updateSelectInput(session, inputId = "remove_row",
choices = 1:nrow(mod_df$x))
})
shiny::observeEvent(input$add, {
mod_df$x <- mod_df$x %>%
dplyr::bind_rows(
dplyr::tibble(Height = as.numeric(input$height),
Weight = as.numeric(input$weight)))
})
shiny::observeEvent(input$remove, {
mod_df$x <- mod_df$x[-as.integer(input$remove_row), ]
})
proxy <- DT::dataTableProxy('table')
shiny::observe({
DT::replaceData(proxy, mod_df$x)
})
}
shinyApp(ui, server)
We can create a reactive with the means of Height and Weight. This will ensure that changes from mod_df$x will be reflected when computing the means.
mean_table_df <- eventReactive(mod_df$x, {
mod_df$x %>%
summarise(across(c("Height", "Weight"), ~ mean(., na.rm = TRUE)))
})
# table 2
output$mean_table <- DT::renderDT({
datatable(mean_table_df())
})
Complete app:
library(shiny)
library(tidyverse)
library(DT)
df <- dplyr::tibble(Height = numeric(), Weight = numeric())
ui <- fluidPage(
# App title ----
titlePanel("DT + Proxy + Replace Data"),
# Sidebar layout with input and output definitions ----
sidebarLayout(
# Sidebar panel for inputs ----
sidebarPanel(
# Input: Slider for the number of bins ----
shiny::textInput(inputId = "height", label = "height"),
shiny::textInput(inputId = "weight", label = "weight"),
shiny::actionButton(inputId = "add", label = "Add"),
shiny::selectInput(
inputId = "remove_row", label = "Remove Row",
choices = 1:nrow(df)
),
shiny::actionButton(inputId = "remove", label = "Remove")
),
# Main panel for displaying outputs ----
mainPanel(
# Output: Histogram ----
DT::DTOutput(outputId = "table"),
DT::DTOutput(outputId = "mean_table"),
)
)
)
# Define server logic required to draw a histogram ----
server <- function(input, output, session) {
mod_df <- shiny::reactiveValues(x = df)
output$table <- DT::renderDT({
mod_df$x
})
shiny::observe({
shiny::updateSelectInput(session,
inputId = "remove_row",
choices = 1:nrow(mod_df$x)
)
})
shiny::observeEvent(input$add, {
mod_df$x <- mod_df$x %>%
dplyr::bind_rows(
dplyr::tibble(
Height = as.numeric(input$height),
Weight = as.numeric(input$weight)
)
)
})
shiny::observeEvent(input$remove, {
mod_df$x <- mod_df$x[-as.integer(input$remove_row), ]
})
proxy <- DT::dataTableProxy("table")
shiny::observe({
DT::replaceData(proxy, mod_df$x)
})
# TABLE 2
mean_table_df <- eventReactive(mod_df$x, {
mod_df$x %>%
summarise(across(c("Height", "Weight"), ~ mean(., na.rm = TRUE)))
})
# table 2
output$mean_table <- DT::renderDT({
datatable(mean_table_df())
})
}
shinyApp(ui, server)
I'm trying to update a selectInput in shinyapp but it doesn't work correctly. When I change the input of datalab_data, the choices in the selectinput datalab_columns don't change and it keep the column names of Events. I hope someone can help me with this part of code:
library(shiny)
library(shinydashboard)
library(dplyr)
header <- dashboardHeader(
title = "dashboard_shiny", titleWidth = 250
)
sidebar <- dashboardSidebar(
width = 250,
sidebarMenu(
menuItem("Data Lab", tabName = "datalab", icon = icon("flask"))
)
)
body <- dashboardBody(
tabItems(
tabItem("datalab",
fluidRow(
column(6, wellPanel(radioButtons("datalab_data", "Select data source:", choices = c("Events", "Worknotes", "Occupations")))),
column(6, wellPanel(selectInput("datalab_columns", "Select data columns:", choices = "All Columns", multiple = T)))
)
)
)
)
ui <- dashboardPage(header, sidebar, body)
server <- function(input, output, session) {
observeEvent(input$datalab_data != "", {
if(input$datalab_data == "Events"){
columns <- events() %>% colnames()
}
if(input$datalab_data == "Worknotes"){
columns <- worknotes() %>% colnames()
}
if(input$datalab_data == "Occupations"){
columns <- occupations() %>% colnames()
}
updateSelectInput(session = session, inputId = "datalab_columns", choices = c("All Columns", columns), selected = "All Columns")
})
}
shinyApp(ui, server)
I have an shiny app that ask the user to upload a file (a tabulated file with data), then it renders this file into a table and the user can filter some values based on numericInput, selectInput, and textAreaInput. The user has to select the filters and then press a button in order to filter the table.
There is no sequential filtering, i.e, the user can fill all the filters or just one. Every time the user choose a filter the value of the other filters get updated (selectInput inputs) and this is the behaviour I want. However, once the Filter button is pressed, I can't see the previous selection and also I can't reset the filters.
What I would like to achieve is to maintain the actual behaviour when updating the filters, i.e, once I choose a filter and press the filter button the other selectInput choices are automatically updated, BUT I want to keep track of the filters choices, so the user can see the filters he/she has selected. That was what I was expecting but everytime I press the button Filter it seems that the filter tab is rendered again.
Here is my app,
library(shiny)
library(vroom)
library(dplyr)
library(shinycssloaders)
library(shinydashboard)
library(shinydashboardPlus)
library(tidyr)
header <- dashboardHeader()
sidebar <- dashboardSidebar(width = 450,
sidebarMenu(id="tabs",
menuItem("Filtros", tabName="filtros", icon = icon("bar-chart-o")),
uiOutput("filtros")
)
)
body <- dashboardBody(
tabItems(
tabItem(tabName="filtros",
fluidRow(
column(12,dataTableOutput("tabla_julio") %>% withSpinner(color="#0dc5c1"))
)
)
)
)
ui <- dashboardPagePlus(enable_preloader = TRUE, sidebar_fullCollapse = TRUE, header, sidebar, body)
server = function(input, output, session) {
#Create the choices for sample input
vals <- reactiveValues(data=NULL)
vals$data <- iris
output$filtros <- renderUI({
datos <- vals$data
conditionalPanel("input.tabs == 'filtros'",
tagList(
div(style="display: inline-block;vertical-align:top; width: 221px;",numericInput(inputId="Sepal.Length", label="Sepal.Length", value=NA, min = NA, max = NA, step = NA)),
div(
div(style="display: inline-block;vertical-align:top; width: 224px;", selectInput(inputId = "Species", label = "Species", width = "220", choices=unique(datos$Species),
selected = NULL, multiple = TRUE, selectize = TRUE, size = NULL))
)
),
actionButton("filtrar", "Filter")
)
})
# create reactiveValues
vals <- reactiveValues(data=NULL)
vals$data <- iris
# Filter data
observeEvent(input$filtrar, {
tib <- vals$data
if (!is.na(input$Sepal.Length)){
tib <- tib %>% dplyr::filter(!Sepal.Length >= input$Sepal.Length)
print(head(tib))
} else { tib <- tib }
# Filter
if (!is.null(input$Species)){
toMatch <- paste0("\\b", input$Species, "\\b")
matches <- unique(grep(paste(toMatch,collapse="|"), tib$Species, value=TRUE))
tib <- tib %>% dplyr::filter(Species %in% matches)
} else { tib <- tib}
tib -> vals$data
print(head(tib, n=15))
})
# Reactive function creating the DT output object
output$tabla_julio <- DT::renderDataTable({
DT::datatable(vals$data)
})
}
shinyApp(ui, server)
Another Update:
library(shiny)
library(vroom)
library(dplyr)
library(shinycssloaders)
library(shinydashboard)
library(shinydashboardPlus)
library(tidyr)
header <- dashboardHeader()
sidebar <- dashboardSidebar(width = 450,
sidebarMenu(id = "tabs",
menuItem(
"Filtros",
tabName = "filtros",
icon = icon("bar-chart-o")
),
uiOutput("filtros")
))
body <- dashboardBody(tabItems(tabItem(tabName = "filtros",
fluidRow(
column(12,
DT::dataTableOutput("tabla_julio") # %>% withSpinner(color = "#0dc5c1")
)
))))
ui <-
dashboardPagePlus(
enable_preloader = FALSE,
sidebar_fullCollapse = TRUE,
header,
sidebar,
body
)
server = function(input, output, session) {
# Create the choices for sample input
vals <- reactiveValues(data = iris, filtered_data = iris)
output$filtros <- renderUI({
datos <- isolate(vals$data)
conditionalPanel(
"input.tabs == 'filtros'",
tagList(
div(
style = "display: inline-block;vertical-align:top; width: 221px;",
numericInput(
inputId = "SepalLength",
label = "Sepal.Length",
value = NA,
min = NA,
max = NA,
step = NA
)
),
div(
div(
style = "display: inline-block;vertical-align:top; width: 224px;",
selectInput(
inputId = "Species",
label = "Species",
width = "220",
choices = unique(isolate(datos$Species)),
selected = NULL,
multiple = TRUE,
selectize = TRUE,
size = NULL
)
)
)
),
actionButton("filtrar", "Filter", style = "width: 100px;"),
actionButton("reset", "Reset", style = "width: 100px;")
)
})
# Filter data
observeEvent(input$filtrar, {
tib <- vals$data
if (!is.na(input$SepalLength)) {
tib <- tib %>% dplyr::filter(Sepal.Length < input$SepalLength)
print(head(tib))
} else {
tib
}
# Filter
if (!is.null(input$Species)) {
tib <- tib %>% dplyr::filter(Species %in% input$Species)
} else {
tib
}
print(head(tib, n = 15))
vals$filtered_data <- tib
updateSelectInput(session, inputId = "Species", selected = input$Species, choices = unique(vals$filtered_data$Species))
})
observeEvent(input$reset, {
updateNumericInput(session, inputId = "SepalLength", value = NA)
updateSelectInput(session, inputId = "Species", selected = "")
})
# Reactive function creating the DT output object
output$tabla_julio <- DT::renderDataTable({
DT::datatable(vals$filtered_data)
}, server = FALSE)
}
shinyApp(ui, server)
Update: Here is what I think you are after. The most important step is to isolate the inputs in renderUI so they aren't re-rendered on every input change.
library(shiny)
library(vroom)
library(dplyr)
library(shinycssloaders)
library(shinydashboard)
library(shinydashboardPlus)
library(tidyr)
header <- dashboardHeader()
sidebar <- dashboardSidebar(width = 450,
sidebarMenu(id = "tabs",
menuItem(
"Filtros",
tabName = "filtros",
icon = icon("bar-chart-o")
),
uiOutput("filtros")
))
body <- dashboardBody(tabItems(tabItem(tabName = "filtros",
fluidRow(
column(12,
DT::dataTableOutput("tabla_julio") # %>% withSpinner(color = "#0dc5c1")
)
))))
ui <-
dashboardPagePlus(
enable_preloader = FALSE,
sidebar_fullCollapse = TRUE,
header,
sidebar,
body
)
server = function(input, output, session) {
# Create the choices for sample input
vals <- reactiveValues(data = iris, filtered_data = iris)
output$filtros <- renderUI({
datos <- isolate(vals$data)
conditionalPanel(
"input.tabs == 'filtros'",
tagList(
div(
style = "display: inline-block;vertical-align:top; width: 221px;",
numericInput(
inputId = "SepalLength",
label = "Sepal.Length",
value = NA,
min = NA,
max = NA,
step = NA
)
),
div(
div(
style = "display: inline-block;vertical-align:top; width: 224px;",
selectInput(
inputId = "Species",
label = "Species",
width = "220",
choices = unique(isolate(datos$Species)),
selected = NULL,
multiple = TRUE,
selectize = TRUE,
size = NULL
)
)
)
),
actionButton("filtrar", "Filter", style = "width: 100px;"),
actionButton("reset", "Reset", style = "width: 100px;")
)
})
# Filter data
observeEvent(input$filtrar, {
tib <- vals$data
if (!is.na(input$SepalLength)) {
tib <- tib %>% dplyr::filter(Sepal.Length < input$SepalLength)
print(head(tib))
} else {
tib
}
# Filter
if (!is.null(input$Species)) {
tib <- tib %>% dplyr::filter(Species %in% input$Species)
} else {
tib
}
print(head(tib, n = 15))
vals$filtered_data <- tib
})
observeEvent(input$reset, {
updateNumericInput(session, inputId = "SepalLength", value = NA)
updateSelectInput(session, inputId = "Species", selected = "")
})
# Reactive function creating the DT output object
output$tabla_julio <- DT::renderDataTable({
DT::datatable(vals$filtered_data)
}, server = FALSE)
}
shinyApp(ui, server)
Initial answer:
I'd recommend using the selectizeGroup-module from library(shinyWidgets).
It creates a
Group of mutually dependent selectizeInput for filtering
data.frame's columns (like in Excel).
Besides the fact, that it only uses selectizeInput it seems to meet your requirements and saves us from a lot of typing.
Here is an example using the iris dataset:
library(shiny)
library(DT)
library(shinyWidgets)
library(datasets)
DF <- iris
names(DF) <- gsub("\\.", "", names(DF))
ui <- fluidPage(
fluidRow(
column(width = 10, offset = 1, tags$h3("Filter data with selectize group")),
column(width = 3, offset = 1,
selectizeGroupUI(
id = "my-filters",
params = list(
SepalLength = list(inputId = "SepalLength", title = "SepalLength:"),
SepalWidth = list(inputId = "SepalWidth", title = "SepalWidth:"),
PetalLength = list(inputId = "PetalLength", title = "PetalLength:"),
PetalWidth = list(inputId = "PetalWidth", title = "PetalWidth:"),
species = list(inputId = "Species", title = "Species:")
),
inline = FALSE
)),
column(
width = 10, offset = 1,DT::dataTableOutput(outputId = "table")
)
)
)
server <- function(input, output, session) {
filtered_table <- callModule(
module = selectizeGroupServer,
id = "my-filters",
data = DF,
vars = names(DF),
inline = FALSE
)
output$table <- DT::renderDataTable(filtered_table())
}
shinyApp(ui, server)
If i understand your question correctly, you are almost at your goal. In this case, you are overwriting your data at run-time. This causes the filter to be invalid, and the reactive UI seems to check this at every click.
A simple solution is to store the original and filtered datasets separately. An alternativ is to store the filters in a reactive-value and re-render the DataTable at run-time, using the filters on the original table. Here I'll go for the first example.
Below I've changed the following:
Added data_print and filters as reactive values for printing and filters
Changed the filtering method for filtrar, making use of data_print, and added some formatting and changed a few lines of code, as an example of code that might be easier to adapt to a given user-input
removed some unnecesary code (renderDataTable changed input to DT automatically)
server = function(input, output, session) {
#Create the choices for sample input
vals <- reactiveValues(
#raw data
data = iris,
#Exists only in order to print.
data_print = iris,
#for filtering data
filters = list(Species = c(),
Sepal.Length = c()
)
)
#in case of many filters, or filters expanding depending on input data, it might be worth adding this to reactiveValues
## Unchanged
output$filtros <- renderUI({
datos <- vals$data
conditionalPanel("input.tabs == 'filtros'",
tagList(
div(style="display: inline-block;vertical-align:top; width: 221px;",
numericInput(inputId="Sepal.Length", label="Sepal.Length",
value=NA, min = NA, max = NA, step = NA)),
div(
div(style="display: inline-block;vertical-align:top; width: 224px;",
selectInput(inputId = "Species", label = "Species", width = "220",
choices=unique(datos$Species),
selected = NULL, multiple = TRUE, selectize = TRUE, size = NULL))
)
),
actionButton("filtrar", "Filter")
)
})
# Filter data
observeEvent(input$filtrar, {
nm <- names(vals$filters)
for(i in nm){
if(is.na(input[[i]]) || is.null(input[[i]]))
vals$filters[[i]] <- unique(vals$data[[i]]) #If unfiltered use all values
else
vals$filters[[i]] <- input[[i]] #if filtered choose the filtered value
}
#Overwrite data_print instead of data. Creds to https://stackoverflow.com/a/47171513/10782538
vals$data_print <- vals$data %>% dplyr::filter((!!as.symbol(nm[1])) %in% vals$filters[[1]],
(!!as.symbol(nm[2]) %in% vals$filters[[2]]))
})
# Reactive function creating the DT output object
output$tabla_julio <- DT::renderDataTable(
vals$data_print #<====renderDataTable changes to data.
)
}
Is is possible to make the tabs interactive for the below code. So, only when I select "B" from the dropdown, Tab B should be open
library(shinydashboard)
library(readxl)
ui <- dashboardPage(
dashboardHeader(title = "Loading data"),
dashboardSidebar(fileInput("datafile","Choose the csv file",multiple = TRUE,
accept = c("text/csv","text/comma-separated-values,text/plain",".csv")),
("Or"),
fileInput("datafile1","Choose the excel file",multiple = TRUE,
accept = c(".xlsx")),
selectInput("S","Select Tabs",choices = c("A","B"))),
dashboardBody(
tabBox(fluidRow(title = "Dataset",uiOutput("filter_70"),width = 5000),fluidRow(title="B"))
))
server <- function(input,output){
}
shinyApp(ui, server)
Here is an example of using tab controls in Shiny.
library(shiny)
library(shinydashboard)
library(tidyverse)
library(magrittr)
header <- dashboardHeader(
title = "My Dashboard",
titleWidth = 500
)
siderbar <- dashboardSidebar(
sidebarMenu(
# Add buttons to choose the way you want to select your data
radioButtons("select_by", "Select by:",
c("Food Type" = "Food",
"Gym Type" = "Gym",
"TV show" = "TV"))
)
)
body <- dashboardBody(
fluidRow(
uiOutput("Output_panel")
),
tabBox(title = "RESULTS", width = 12,
tabPanel("Visualisation",
width = 12,
height = 800
)
)
)
ui <- dashboardPage(header, siderbar, body, skin = "purple")
server <- function(input, output, session){
nodes_data_1 <- data.frame(id = 1:15,
Food = as.character(c("Edibles", "Fried", "Home Cooked", "packaged", "vending machine")),
Product_name = as.character(c("Bacon", "Cheese", "eggs", "chips", "beans", "oast", "oats and beans", "fried beans", "chickpeas", "broad beans", "garbanzo", "oat bars", "dog meat", "cat food", "horse meat")),
Gym_type = as.character(paste("Gym", 1:15)), TV =
sample(LETTERS[1:3], 15, replace = TRUE))
# build a edges dataframe
edges_data_1 <- data.frame(from = trunc(runif(15)*(15-1))+1,
to = trunc(runif(15)*(15-1))+1)
# create reactive of nodes
nodes_data_reactive <- reactive({
nodes_data_1
}) # end of reactive
# create reacive of edges
edges_data_reactive <- reactive({
edges_data_1
}) # end of reactive
# The output panel differs depending on the how the data is selected
# so it needs to be in the server section, not the UI section and created
# with renderUI as it is reactive
output$Output_panel <- renderUI({
# When selecting by workstream and issues:
if(input$select_by == "Food") {
box(title = "Output PANEL",
collapsible = TRUE,
width = 12,
do.call(tabsetPanel, c(id='t',lapply(1:length(unique(nodes_data_reactive()$Food)), function(i) {
food <- unique(sort(as.character(nodes_data_reactive()$Food)))
tabPanel(food[i],
checkboxGroupInput(paste0("checkboxfood_", i),
label = NULL,
choices = nodes_data_reactive() %>%
filter(Food == food[i]) %>%
select(Product_name) %>%
unlist(use.names = FALSE)),
checkboxInput(paste0("all_", i), "Select all", value = TRUE)
)
})))
) # end of Tab box
# When selecting by the strength of links connected to the issues:
} else if(input$select_by == "Gym") {
box(title = "Output PANEL", collapsible = TRUE, width = 12,
checkboxGroupInput("select_gyms", "Select gyms you want to display", choices = unique(nodes_data_reactive()$Gym_type)
,
selected = NULL,
inline = FALSE
)# end of checkboxGroupInput
) # end of box
} else if(input$select_by == "TV") {
box(title = "Output PANEL", collapsible = TRUE, width = 12,
checkboxGroupInput("select_tvs",
"Select the tv shows you want to see",choices = sort(unique(nodes_data_reactive()$TV)),
selected = NULL,
inline = FALSE
)# end of checkboxGroupInput
) # end of box
} # end of else if
}) # end of renderUI
observe({
lapply(1:length(unique(nodes_data_reactive()$Food)), function(i) {
food <- unique(sort(as.character(nodes_data_reactive()$Food)))
product_choices <- nodes_data_reactive() %>%
filter(Food == food[i]) %>%
select(Product_name) %>%
unlist(use.names = FALSE)
if(!is.null(input[[paste0("all_", i)]])){
if(input[[paste0("all_", i)]] == TRUE) {
updateCheckboxGroupInput(session,
paste0("checkboxfood_", i),
label = NULL,
choices = product_choices,
selected = product_choices)
} else {
updateCheckboxGroupInput(session,
paste0("checkboxfood_", i),
label = NULL,
choices =product_choices)
}
}
})
})
} # end of server
# Run the application
shinyApp(ui = ui, server = server)
Now, if you want to use Shiny to import datasets and have some tab controls to select different views, you can do it this way.
library(shiny)
library(ggplot2)
#ui.R
ui <- fluidPage(
titlePanel("My shiny app"), sidebarLayout(
sidebarPanel(
helpText("This app shows how a user can upload a csv file. Then, plot the data.
Any file can be uploaded but analysis is only available
if the data is in same format as the sample file, downloadable below
"),
a("Data to be plotted", href="https://www.dropbox.com/s/t3q2eayogbe0bgl/shiny_data.csv?dl=0"),
tags$hr(),
fileInput("file","Upload the file"),
h5(helpText("Select the read.table parameters below")),
checkboxInput(inputId = 'header', label = 'Header', value = TRUE),
checkboxInput(inputId = "stringAsFactors", "stringAsFactors", FALSE),
br(),
radioButtons(inputId = 'sep', label = 'Separator', choices = c(Comma=',',Semicolon=';',Tab='\t', Space=''), selected = ',')
),
mainPanel(
uiOutput("tb"),
plotOutput("line")
)
)
)
#server.R
server <- function(input,output){
data <- reactive({
file1 <- input$file
if(is.null(file1)){return()}
read.table(file=file1$datapath, sep=input$sep, header = input$header, stringsAsFactors = input$stringAsFactors)})
output$filedf <- renderTable({
if(is.null(data())){return ()}
input$file
})
output$sum <- renderTable({
if(is.null(data())){return ()}
summary(data())
})
output$table <- renderTable({
if(is.null(data())){return ()}
data()
})
output$line <- renderPlot({
if (is.null(data())) { return() }
print(ggplot(data(), aes(x=date, y=aa)) + geom_line()+ facet_wrap(~station)) })
output$tb <- renderUI({if(is.null(data()))
h5()
else
tabsetPanel(tabPanel("About file", tableOutput("filedf")),tabPanel("Data", tableOutput("table")),tabPanel("Summary", tableOutput("sum")))
})
}
shinyApp(ui = ui, server = server)
I'm building an app with shinyDashboard. I want to display several selectInput in sidebarMenu regarding the selected tabItem AND tabPanel. The same selectInput are used in different tabItem.
It looks simple but I struggle with the conditional syntax in conditionalPanel using multiples arguments with both AND (&&), OR (||) and IN (%in%) operators. I tried to add bracket but it is not doing the job.
I wrote this code, with is reproductible and working but not doing what I want as its always display the selectInputs.
library(shinydashboard)
library(dplyr)
mtcars$gear <- as.character(mtcars$gear)
all_gears <- sort(unique(mtcars$gear))
mtcars$cyl <- as.character(mtcars$cyl)
all_cyl <- sort(unique(mtcars$cyl))
ui <- dashboardPage(
dashboardHeader(title = "test"),
dashboardSidebar(
sidebarMenu(id="menu1",
menuItem(
"Dashboard",
tabName = "dashboard",
icon = icon("dashboard")
),
menuItem(
"Indicators",
tabName = "indicators",
icon = icon("info-circle")
)
),
conditionalPanel(
condition = "input.menu1 == 'dashboard' && input.tabselected %in% c('1','2')",
selectInput(
inputId = "cylinders",
label = "Select number of cylinders",
choices = all_cyl,
selected = '4',
multiple = TRUE,
selectize = FALSE
)
),
conditionalPanel(
condition = "(input.menu1 == 'dashboard' && input.tabselected == 2) || input.menu1 == 'indicators'",
selectInput(
inputId = "gearsnumber",
label = "Select number of gears",
choices = all_gears,
selected = '3',
multiple = TRUE,
selectize = FALSE
)
)
),
dashboardBody(
tabItems(
tabItem(tabName = "dashboard",
tabsetPanel(
tabPanel("Graph", value=1, plotOutput("plot")),
tabPanel("Table", value=2, dataTableOutput("table")),
tabPanel("Empty", value=3)
)
),
tabItem(tabName = "indicators",
infoBoxOutput("totalweight")
)
)
)
)
server <- function(input, output, session) {
selectedDatacyl <- reactive({
req(input$cylinders)
df <- as.data.frame(mtcars)
df$gear <- as.character(df$gear)
df$cyl <- as.character(df$cyl)
df <- mtcars
df %>% dplyr::filter(cyl %in% input$cylinders)
})
selectedDatagears <- reactive({
req(input$gearsnumber)
df <- selectedDatacyl()
df %>% dplyr::filter(gear %in% input$gearsnumber)
})
output$plot <- renderPlot({
ggplot( data = selectedDatacyl(), aes(x = rownames(selectedDatacyl()), y = mpg)) + geom_point()
})
output$table <- DT::renderDataTable({
DT::datatable( data = selectedDatagears(),
options = list(pageLength = 14),
rownames = FALSE)
})
output$totalweight <- renderInfoBox({
infoBox(
"Total weight",
paste0(sum(selectedDatagears()$wt), "lbs"),
icon = icon("chart-area"),
color = "green"
)
})
}
shinyApp(ui = ui, server = server)
What should I do to make thoses conditions operational? Thanks to all contribs.
The condition in conditionalPanel is a JavaScript expression, not a R expression.
So you have to replace
input.menu1 == 'dashboard' && input.tabselected %in% c('1','2')
with
input.menu1 == 'dashboard' && (input.tabselected == '1' || input.tabselected == '2')
or
input.menu1 == 'dashboard' && ['1','2'].indexOf(input.tabselected) > -1