UpdateSliderInput not working...
Hi All,
Seems like a challenge updating sliderInput. So i wanted to develop an application in a way so that filter can be applied dynamically wherein one of the variables needs to be provided with a slider.
Any help can be really appriciable.
library(shiny)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
fluidRow(
column(6, actionButton('addFilter', 'Add filter')),
offset = 6
),
tags$hr(),
tags$div(id = 'placeholderAddRemFilt'),
tags$div(id = 'placeholderFilter'),
tags$div(id = 'placeholderFilter')
# width = 4 # sidebar
),
mainPanel(
tableOutput("data")
)
)
)
server <- function(input, output,session) {
filter <- character(0)
makeReactiveBinding("aggregFilterObserver")
aggregFilterObserver <- list()
observeEvent(input$addFilter, {
add <- input$addFilter
filterId <- paste0('Filter_', add)
colfilterId <- paste0('Col_Filter_', add)
rowfilterId <- paste0('Row_Filter_', add)
removeFilterId <- paste0('Remove_Filter_', add)
headers <- names(mtcars)
insertUI(
selector = '#placeholderFilter',
# ui = tags$div(id = filterId,
# actionButton(removeFilterId, label = "Remove filter", style = "float: right;"),
# selectInput(colfilterId, label = "Some Filter", choices = as.list(headers), selected = 1),
# sliderInput(rowfilterId, label = "Select variable values",
# min = 1, max = 2, value = 1:4)
# )
ui = tags$div(column(9,id = filterId,
actionButton(removeFilterId, label = "Remove filter", style = "float: right;"),
selectInput(colfilterId, label = "Some Filter", choices = headers, selected = NULL),
conditionalPanel(condition = paste0("input.",colfilterId," != 'mpg'"),
checkboxGroupInput(rowfilterId, label = "Select variable values",
choices = NULL, selected = NULL, width = 4000)),
conditionalPanel(condition = paste0("input.",colfilterId," == 'mpg'"),
sliderInput(rowfilterId,
label = 'select values',
min = 1,#min(datafile$Age),
max = 10,#max(datafile$Age),
value = 1:5))#c(min(datafile$Age),max(datafile$Age))))
)
)
)
observeEvent(input[[colfilterId]], {
col <- input[[colfilterId]]
values <- as.list(unique(mtcars[col]))[[1]]
print(values)
print(paste0("example",as.list(unique(mtcars[col]))))
#
# updateCheckboxGroupInput(session, rowfilterId , label = "Select variable values",
# choices = values, selected = values, inline = TRUE)
#
updateSliderInput(session, rowfilterId , min = min(values), max = max(values), value = c(min(values),max(values)))
updateCheckboxGroupInput(session, rowfilterId , label = "Select variable values",
choices = values, selected = values, inline = TRUE)
aggregFilterObserver[[filterId]]$col <<- col
aggregFilterObserver[[filterId]]$rows <<- NULL
})
observeEvent(input[[rowfilterId]], {
rows <- input[[rowfilterId]]
aggregFilterObserver[[filterId]]$rows <<- rows
})
observeEvent(input[[removeFilterId]], {
removeUI(selector = paste0('#', filterId))
aggregFilterObserver[[filterId]] <<- NULL
})
})
output$data <- renderTable({
dataSet <- mtcars
invisible(lapply(aggregFilterObserver, function(filter){
dataSet <<- dataSet[which((dataSet[[filter$col]] %in% filter$rows)), ]
}))
dataSet
})
}
shinyApp(ui = ui, server = server)
Mpg values are not being updated, Is this due to conditionalPanel because of which the sliderInput is not being updated?
Everything seems to be perfect apart from the inputid you are using for 2 input types.
I just created one more variable for Sliderinput which will create dynamic input id.
library(shiny)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
fluidRow(
column(6, actionButton('addFilter', 'Add filter')),
offset = 6
),
tags$hr(),
tags$div(id = 'placeholderAddRemFilt'),
tags$div(id = 'placeholderFilter'),
width = 4 # sidebar
),
mainPanel(
tableOutput("data")
)
)
)
server <- function(input, output,session) {
filter <- character(0)
makeReactiveBinding("aggregFilterObserver")
aggregFilterObserver <- list()
observeEvent(input$addFilter, {
add <- input$addFilter
filterId <- paste0('Filter_', add)
colfilterId <- paste0('Col_Filter_', add)
rowfilterId <- paste0('Row_Filter_', add)
rowfilterId_num <- paste0('Row_Filter_num_', add)
removeFilterId <- paste0('Remove_Filter_', add)
headers <- names(mtcars)
insertUI(
selector = '#placeholderFilter',
ui = tags$div(id = filterId,
actionButton(removeFilterId, label = "Remove filter", style = "float: right;"),
selectInput(colfilterId, label = "Some Filter", choices = as.list(headers), selected = 1),
sliderInput(rowfilterId_num, label = "Select variable values",
min = 1, max = 2, value = 1:4)
)
)
observeEvent(input[[colfilterId]], {
print(rowfilterId)
print(paste0(input[[colfilterId]]))
col <- input[[colfilterId]]
values <- as.list(unique(mtcars[col]))[[1]]
print(values)
print(paste0("example",as.list(unique(mtcars[col]))))
updateCheckboxGroupInput(session, rowfilterId , label = "Select variable values",
choices = values, selected = values, inline = TRUE)
updateSliderInput(session, rowfilterId_num , label = "Select variable",min = min(values), max = max(values), value = c(min(values),max(values)))
aggregFilterObserver[[filterId]]$col <<- col
aggregFilterObserver[[filterId]]$rows <<- NULL
})
observeEvent(input[[rowfilterId]], {
rows <- input[[rowfilterId]]
aggregFilterObserver[[filterId]]$rows <<- rows
})
observeEvent(input[[removeFilterId]], {
removeUI(selector = paste0('#', filterId))
aggregFilterObserver[[filterId]] <<- NULL
})
})
output$data <- renderTable({
dataSet <- mtcars
invisible(lapply(aggregFilterObserver, function(filter){
dataSet <<- dataSet[which((dataSet[[filter$col]] %in% filter$rows)), ]
}))
dataSet
})
}
shinyApp(ui = ui, server = server)
just check and let me know that this is what you wanted to achieve. let me know incase any thing else is required.
Related
Hi I would appreciate your help.
I have the attached code. I import an excel data file and read the data. I have a renderUi command which by selectInput, reads the names of the inserted table and plots the relative columns of the data table.
When I run the code and I select the ParameterName_time and ParameterName ( which are the x and y parts of the plot ) , I can see the plot for just half a second but then it dissapears and the choices are back in the original state.
It looks like it is working but can not store the result.
Maybe I need to use the updateselectInput command or it is something with the reactivity of hte inputs or the plot. please help !
# Define server function
server <- function(input,output,session) {[enter image description here][1]
Excel <- reactive({ # DATA IMPORT ------------------------------------------
inFile <- input$Excel
if (is.null(inFile)) { return(NULL) }
dataFile <- read_excel(inFile$datapath,sheet=1)
return(dataFile)
})
RV <- reactiveValues(Excel = data.frame())
output$Table_Of_Data = DT::renderDataTable({ # DATA TABLE ------------------------------------------
RV$Excel<-Excel()
},options = list(scrollX = TRUE))
# if (input$submitbutton_Show_Table>0){
# }
output$summary <- renderPrint({ # Summary of DATA TABLE ------------------------------------------
dataset <- Excel()
summary(dataset)
})
# RValsl <- reactive(input$NumberOfDates_L )
# RValsr<- reactive(input$NumberOfDates_R )
output$timeDataSetNumber <- renderUI({
fluidRow(
numericInput(inputId = "NumberOfDates_L", # INPUT PARAMETER
label = "Number Of Different Time Data Sets (Left Side):",
value = 1 ,
min = 1,
),
numericInput(inputId = "NumberOfDates_R", # INPUT PARAMETER
label = "Number Of Different Time Data Sets (Right Side):",
value = 1 ,
min = 1,
)
)
})
output$Plotoutput <- renderPlot({
n<-input$NumberOfDates_L
output$tabsets <- renderUI({
Panels <- lapply(1:n, function(number){
tabPanel(paste0("Set #", number),
fluidRow(
selectInput("ParameterName_time","Select the Date vector for this entry",names(RV$Excel),multiple = TRUE ),
selectInput("ParameterName", "Select the KPIs for this entry:", names(RV$Excel) ,multiple = TRUE ),
),
)
})
do.call(tabsetPanel,Panels)
})
#============
k<-input$NumberOfDates_R
output$tabsets_R <- renderUI({
Panels_R <- lapply(1:k, function(number){
tabPanel(paste0("Set #", number),
fluidRow(
selectInput("ParameterName_time_R","Select the Date vector for this entry",names(RV$Excel)),
selectInput("ParameterName_R", "Select the KPIs for this entry:",names(RV$Excel),multiple = TRUE),
),
)
})
do.call(tabsetPanel,Panels_R)
})
Excel<-RV$Excel ##########################################################
###############################
###################################################
# if (input$submitbutton>0){
source(file = "path................TimeVector.R")
TVmean=TimeVector(input$Starting_Date,input$Ending_Date,input$Time)[,1]
TV1=TimeVector(input$Starting_Date,input$Ending_Date,input$Time)[,2]
TV2=TimeVector(input$Starting_Date,input$Ending_Date,input$Time)[,3]
#====================================================
# Value<- Excel %>% select(c(input$ParameterName))
source(file = "C:/Users/AntoniosTriantos/OneDrive - ClearWELL Oilfield Solutions/Desktop/App/Scripts/ReducedParameter.R")
# Left Side of the plot
kpi_entries=length(input$ParameterName)
# kpi_Time_entries=length(input$ParameterName_time)
KPITable=c(TVmean)
for ( i in 1:kpi_entries){
# for ( j in 1:kpi_Time_entries){
AV_Prop_Value_reduced=ReducedParameter(input$ParameterName_time[1],input$ParameterName[i],Excel,TV1,TV2)
KPITable=(cbind.data.frame(KPITable,AV_Prop_Value_reduced ))
}
# }
# Right Side of the plot
if (length(input$ParameterName_R)>0){
kpi_entries_R=length(input$ParameterName_R)
KPITable_R=c(TVmean)
for ( i in 1:kpi_entries_R){
AV_Prop_Value_reduced_R=ReducedParameter(input$ParameterName_time_R[1],input$ParameterName_R[i],Excel,TV1,TV2)
KPITable_R=(cbind.data.frame(KPITable_R,AV_Prop_Value_reduced_R ))
}
}
#====================================================
source(file = "path................Plot.R")
Plot<-PlotFunction(TVmean,AV_Prop_Value_reduced,kpi_entries,KPITable,input$ParameterName_R,kpi_entries_R,KPITable_R)
# }
})
}
ui <- fluidPage(theme = shinytheme("cerulean"),
navbarPage(
# theme = "cerulean", # <--- To use a theme, uncomment this
"ClearKPI",
tabPanel("Navbar 1",
sidebarPanel(wellPanel(fileInput('Excel', 'Choose XLSX File',
accept=c('sheetName', 'header'), multiple=FALSE))),
# actionButton("submitbutton_Show_Table","Show table",class ="btn btn-primary"),
h1("Excel Data"),
DT::dataTableOutput("Table_Of_Data"), # SHOW DATA TABLE
# Output: Verbatim text for data summary ----
verbatimTextOutput("summary"),
headerPanel("KPI Entry Point") , # INPUT KPIs vs Dates PARAMETER
uiOutput("timeDataSetNumber") ,
mainPanel(h2("Left side of the plot - Input:"),
uiOutput("tabsets")),
mainPanel(h2("Right side of the plot - Input:"),
uiOutput("tabsets_R")),
headerPanel("Edit Plot") , # INPUT KPIs vs Dates PARAMETER
numericInput(inputId = "Time", # INPUT PARAMETER
label = "Number of Hours to round:",
value = 4),
dateInput(
inputId="Starting_Date" ,
label="Starting Date:",
value = "2022-02-08",
min = NULL,
max = NULL,
format = "yyyy-mm-dd",
startview = "year",
weekstart = 0,
language = "en",
width = NULL,
autoclose = TRUE,
datesdisabled = NULL,
daysofweekdisabled = NULL),
dateInput( # INPUT PARAMETER
inputId="Ending_Date" ,
label="Ending Date:",
value = "2022-06-27",
min = NULL,
max = NULL,
format = "yyyy-mm-dd",
startview = "year",
weekstart = 0,
language = "en",
width = NULL,
autoclose = TRUE,
datesdisabled = NULL,
daysofweekdisabled = NULL),
# actionButton("submitbutton","Submit",class ="btn btn-primary"),
mainPanel(h2("Plot:"),
plotOutput(outputId = "Plotoutput", width = 1250 , height = 800) # OUTPUT PARAMETER
), # mainPanel
)
)
)
rm(list = ls())
source(file = "path................UI.R")
source(file = "path................SERVER.R")
# Create Shiny object
shinyApp(ui = ui, server = server)
I found the answer.
You need to introduce the actionbuttons to stop the procedure for being reactive and then you need to introduce both selectInpout and UpdateSelectInput commands.
# Define server function
server <- function(input,output,session) {
Excel <- reactive({ # DATA IMPORT ------------------------------------------
inFile <- input$Excel
if (is.null(inFile)) { return(NULL) }
dataFile <- read_excel(inFile$datapath,sheet=1)
return(dataFile)
})
RV <- reactiveValues(Excel = data.frame())
output$Table_Of_Data = DT::renderDataTable({ # DATA TABLE ------------------------------------------
if((input$submitbutton_Show_Table %% 2) == 0){
RV$Excel<-Excel()
}
},options = list(dom='Bfrtip',buttons=list('copy','pdf','csv','excel','print')) , extensions='Buttons')
# if (input$submitbutton_Show_Table>0){
# }
output$summary <- renderPrint({ # Summary of DATA TABLE ------------------------------------------
if((input$submitbutton_Summary %% 2) == 0){
dataset <- Excel()
summary(dataset)
}
})
output$Plotoutput <- renderPlot({
Excel<-isolate(RV$Excel )
#==================
RValsl <- (input$NumberOfDates_L )
RValsr<- (input$NumberOfDates_R )
output$timeDataSetNumber <- renderUI({
fluidRow(
numericInput(inputId = "NumberOfDates_L", # INPUT PARAMETER
label = "Number Of Different Time Data Sets (Left Side):",
value = RValsl()) ,
numericInput(inputId = "NumberOfDates_R", # INPUT PARAMETER
label = "Number Of Different Time Data Sets (Right Side):",
value = RValsr())
)
})
#===========================
if ((input$submitbuttonENTERKPIS %% 2) == 0) {
n<-input$NumberOfDates_L
output$tabsets <- renderUI({
Panels <- lapply(1:n, function(number){
tabPanel(paste0("Set #", number),
fluidRow(
selectInput("ParameterName_time","Select the Date vector for this entry",names(RV$Excel) ),
selectInput("ParameterName", "Select the KPIs for this entry:", names(RV$Excel) ,multiple = TRUE ),
),
)
})
updateSelectInput(session, "ParameterName_time",
label ="Select the Date vector for this entry" ,
choices = names(RV$Excel) )
updateSelectInput(session, "ParameterName",
label ="Select the KPIs for this entry:" ,
choices = names(RV$Excel) )
do.call(tabsetPanel,Panels)
})
#============
k<-input$NumberOfDates_R
output$tabsets_R <- renderUI({
Panels_R <- lapply(1:k, function(number){
tabPanel(paste0("Set #", number),
fluidRow(
selectInput("ParameterName_time_R","Select the Date vector for this entry",names(RV$Excel)),
selectInput("ParameterName_R", "Select the KPIs for this entry:",names(RV$Excel),multiple = TRUE),
),
)
})
updateSelectInput(session, "ParameterName_time_R",
label ="Select the Date vector for this entry" ,
choices = names(RV$Excel) )
updateSelectInput(session, "ParameterName_R",
label ="Select the KPIs for this entry:" ,
choices = names(RV$Excel) )
do.call(tabsetPanel,Panels_R)
})
}
# Excel<-RV$Excel ##########################################################
###############################
###################################################
if ((input$submitbutton %% 2) == 0) {
source(file = "C:/Users/AntoniosTriantos/OneDrive - ClearWELL Oilfield Solutions/Desktop/App/Scripts/TimeVector.R")
TVmean=TimeVector(input$Starting_Date,input$Ending_Date,input$Time)[,1]
TV1=TimeVector(input$Starting_Date,input$Ending_Date,input$Time)[,2]
TV2=TimeVector(input$Starting_Date,input$Ending_Date,input$Time)[,3]
#====================================================
# Value<- Excel %>% select(c(input$ParameterName))
source(file = "C:/Users/AntoniosTriantos/OneDrive - ClearWELL Oilfield Solutions/Desktop/App/Scripts/ReducedParameter.R")
# Left Side of the plot
kpi_entries=length(input$ParameterName)
# kpi_Time_entries=length(input$ParameterName_time)
KPITable=c(TVmean)
for ( i in 1:kpi_entries){
# for ( j in 1:kpi_Time_entries){
AV_Prop_Value_reduced=ReducedParameter(input$ParameterName_time[1],input$ParameterName[i],Excel,TV1,TV2)
KPITable=(cbind.data.frame(KPITable,AV_Prop_Value_reduced ))
}
# }
# Right Side of the plot
if (length(input$ParameterName_R)>0){
kpi_entries_R=length(input$ParameterName_R)
KPITable_R=c(TVmean)
for ( i in 1:kpi_entries_R){
AV_Prop_Value_reduced_R=ReducedParameter(input$ParameterName_time_R[1],input$ParameterName_R[i],Excel,TV1,TV2)
KPITable_R=(cbind.data.frame(KPITable_R,AV_Prop_Value_reduced_R ))
}
}
#====================================================
source(file = "C:/Users/AntoniosTriantos/OneDrive - ClearWELL Oilfield Solutions/Desktop/App/Scripts/Plot.R")
Plot<-PlotFunction(TVmean,AV_Prop_Value_reduced,kpi_entries,KPITable,input$ParameterName_R,kpi_entries_R,KPITable_R)
}
})
}
I need to update/reverse two inputs from drop down inputs upon a button press. At the moment when I hit the swap button (reverse_xz), it reacts however the updatePickerInput doesn't switch my x and z inputs.
I wanted to have the functionality where, once the swap button is clicked, switch the already selected pickerInputs. Then, all the drop down choices (including the selected) need to get reversed. The reason we have to remove the selected choices from vector is to prevent duplicate selections in both x and z inputs.
I am not sure if I have to render the pickerInput ui on the server side?!
This is my code below:
#global.R
library(shiny)
library(shinydashboard)
library(shinydashboardPlus)
library(shinyWidgets)
library(shinyjs)
#variable labels
my_vars <- c("None"= "NONE",
"All" = "all_all",
"Pro" = "Pro_",
"Locomania" = "locomania_Type",
"Racer" = "race")
#ui.R
ui <- shinydashboardPlus::dashboardPage(
header = shinydashboardPlus::dashboardHeader( ),
body = shinydashboard::dashboardBody( box(textOutput("inputs") ) ),
sidebar = shinydashboardPlus::dashboardSidebar(
shinyWidgets::pickerInput(
inputId = "xvar",
label = "X Axis: ",
choices = my_vars,
options = list(
size = 5),
multiple = FALSE,
selected = "all_all"
),
# Button to reverse the choices
shiny::fluidRow(
shiny::column(12, offset = 4,
shinyWidgets::actionBttn(
inputId = "reverse_xz",
label = "",
style = "simple",
color = "primary",
icon = icon("retweet")
)
)
),
shinyWidgets::pickerInput(
inputId = "zvar",
label = "Z Axis: ",
choices = my_vars,
options = list(
size = 5),
multiple = FALSE,
selected = "race"
)
)
)
#server.R
server <- function(input, output, session) {
#
observe({
if(!is.null(input$reverse_xz))
shinyWidgets::updatePickerInput(session, "zvar",
choices = my_vars[!(my_vars %in% input$xvar)],
selected = isolate(input$zvar) )
shinyWidgets::updatePickerInput(session, "xvar",
choices = my_vars[!(my_vars %in% input$zvar)],
selected = isolate(input$xvar) )
})
# These observers remove the selected choices so both pickers are unique
observe({
if(!is.null(input$zvar))
shinyWidgets::updatePickerInput(session, "xvar",
choices = my_vars[!(my_vars %in% input$zvar)],
selected = isolate(input$xvar) )
})
observe({
if(!is.null(input$xvar))
shinyWidgets::updatePickerInput(session, "zvar",
choices = my_vars[!(my_vars %in% input$xvar)],
selected = isolate(input$zvar) )
})
# output inputs
output$inputs <- renderText({ paste0("x var: ", input$xvar,
"\n\n\n z var:", input$zvar,
"\n\n\nreverse press: ", input$reverse_xz) })
}
shiny::shinyApp(ui= ui, server= server)
Thank you in advance. I have looked at some relavant posts however they couldn't guide me much:
Updatepickerinput with change in pickerinput in Shiny
updatePickerInput not updating values after changing tabs in R shiny
update pickerInput by using updatePickerInput in shiny
Look at this and check if it would be OK for you:
#global.R
library(shiny)
library(shinydashboard)
library(shinydashboardPlus)
library(shinyWidgets)
library(shinyjs)
#variable labels
my_vars <- c("None"= "NONE",
"All" = "all_all",
"Pro" = "Pro_",
"Locomania" = "locomania_Type",
"Racer" = "race")
#ui.R
ui <- shinydashboardPlus::dashboardPage(
header = shinydashboardPlus::dashboardHeader( ),
body = shinydashboard::dashboardBody( box(textOutput("inputs") ) ),
sidebar = shinydashboardPlus::dashboardSidebar(
shinyWidgets::pickerInput(
inputId = "xvar",
label = "X Axis: ",
choices = my_vars,
options = list(
size = 5),
multiple = FALSE,
selected = "all_all"
),
# Button to reverse the choices
shiny::fluidRow(
shiny::column(12, offset = 4,
shinyWidgets::actionBttn(
inputId = "reverse_xz",
label = "",
style = "simple",
color = "primary",
icon = icon("retweet")
)
)
),
shinyWidgets::pickerInput(
inputId = "zvar",
label = "Z Axis: ",
choices = my_vars,
options = list(
size = 5),
multiple = FALSE,
selected = "race"
)
)
)
#server.R
server <- function(input, output, session) {
#
observeEvent(input$reverse_xz, {
shinyWidgets::updatePickerInput(session, "zvar",
choices = my_vars[!(my_vars %in% input$zvar)],
selected = input$xvar)
shinyWidgets::updatePickerInput(session, "xvar",
choices = my_vars[!(my_vars %in% input$xvar)],
selected = input$zvar)
})
observe({
if (input$xvar == input$zvar && (length(input$zvar) > 0 && length(input$xvar) > 0)) {
shinyWidgets::updatePickerInput(session, "zvar",
selected = "")
shinyWidgets::updatePickerInput(session, "xvar",
selected = "")
}
})
# output inputs
output$inputs <- renderText({ paste0("x var: ", input$xvar,
"\n\n\n z var:", input$zvar,
"\n\n\nreverse press: ", input$reverse_xz) })
}
shiny::shinyApp(ui= ui, server= server)
I think that maybe this needs an explanation:
if (input$xvar == input$zvar && (length(input$zvar) > 0 && length(input$xvar) > 0))
So, when user choose two the same inputs, then we are updating pickerInputs, so both will have "Nothing selected" as a sign for user that something goes wrong (or that she/he did something wrong). However, "Nothing selected" is like NULL and we can't use NULL like this NULL == "something" inside if, so I'm checking if some input is NULL using length(input$) > 0, because length of NULL is 0. Instead of length(input$) > 0 you could use !is.null(input$) and maybe you should as it is probably more readable, but I'm leaving this decision for you.
I am trying to build a function which will select the data variables entered from the file and show the data variables to be selected via the dropdown and to display the variable that is selected currently.
Here, I am able to add file and show the variables of data in the dropdown in the Filter Tab, however I am unable to catch the currently selected variable in the server to apply filter.
Below is the code
server.R
library(shiny)
library(shinyBS)
library(shinyjs)
server <- function(input, output, session) {
myValue <- reactiveValues()
# Import Data File
observeEvent(input$data_import,{
if(is.null(input$datafile))
myValue$data<-NULL
inFile<-input$datafile
myValue$data <- rio::import(inFile$datapath)
})
# Render Input DataTable
output$show_data <- DT::renderDataTable(
myValue$data, server = FALSE, escape = FALSE, selection = 'none'
)
#Functions
shinyInput <- function(FUN, len, id, ...) {
inputs <- character(len)
for (i in seq_len(len)) {
inputs[i] <- as.character(FUN(paste0(id, i), ...))
}
inputs
}
SingleshinyInput <- function(FUN, i, id, ...) {
inputs <- character(i)
inputs <- as.character(FUN(paste0(id, i), ...))
inputs
}
#Display Dynamic Input Filter table
observe({
if(is.null(myValue$data))
return()
Names <- colnames(myValue$data)
myValue$Filter = data.frame(
Logic = c(NA,shinyInput(selectInput, 4, 'logic_', label = "", choices = c("And","Or"))),
Variable = shinyInput(selectInput, 5, 'var_', label = "", choices = Names ),
Filter = shinyInput(actionButton, 5, 'go_button_', label = "Filter", onclick = 'Shiny.onInputChange(\"select_button\", this.id)' ),
Remove = shinyInput(actionButton, 5, 'remove_button_', "", icon = icon("close"), onclick = 'Shiny.onInputChange(\"select_remove_button\", this.id)' ),
stringsAsFactors = FALSE,
row.names = 1:5
)
}
)
#Add new Filter Row
observeEvent(input$addnewRow,{
if(is.null(myValue$Filter))
return()
i <- as.character(max(as.numeric(row.names(myValue$Filter)))+1)
newRow <- data.frame(Logic = SingleshinyInput(selectInput, i, 'logic_', label = "", choices = c("And","Or")),
Variable = SingleshinyInput(selectInput, i, 'var_', label = "", choices = Names ),
Filter = SingleshinyInput(actionButton, i, 'go_button_', label = "Filter", onclick = 'Shiny.onInputChange(\"select_button\", this.id)' ),
Remove = SingleshinyInput(actionButton, i, 'remove_button_', "", icon = icon("close"), onclick = 'Shiny.onInputChange(\"select_remove_button\", this.id)' ),
stringsAsFactors = FALSE,
row.names = i)
myValue$Filter <- rbind(myValue$Filter,newRow)
})
# Render Filter Data Table
output$data <- DT::renderDataTable(
myValue$Filter, server = FALSE, escape = FALSE, selection = 'none'
)
# Remove filter Row
observeEvent(input$select_remove_button,{
if(is.null(myValue$Filter))
return()
rowToRemove<-unlist(strsplit(input$select_remove_button,"_"))
rowToRemove<-rowToRemove[length(rowToRemove)]
rowToRemove<-which(row.names(myValue$Filter)==rowToRemove)
myValue$Filter<-myValue$Filter[-rowToRemove,]
if(!is.na(myValue$Filter$Logic[1]))
myValue$Filter$Logic[1]<-NA
})
# Display bsModal for filter
observeEvent(input$select_button, {
toggleModal(session,"CustomDataFilter",toggle="open")
})
# Select the variable value selected in the select Input
output$FilterDataSettings <- renderUI({
selected<-unlist(strsplit(input$select_button,"_"))
selected<-as.numeric(selected[length(selected)])
Names <- colnames(myValue$data)
selected_var<-Names[selected]
print(selected_var)
selected<-as.numeric(selected)
print(input[[paste0("var_",selected)]])
return(NULL)
})
output$result <- renderText({
selected<-unlist(strsplit(input$select_button,"_"))
selected<-as.numeric(selected[length(selected)])
paste("You chose", input[[paste0("var_",selected)]])
print(input[[paste0("var_",selected)]])
})
# Show Table Dimensions
output$showDataDimensions.FilterData <- renderUI({
if(is.null(myValue$data)){
return(paste("The data is not selected "))
}
Dim<-dim(myValue$data)
paste("Dimensions", Dim[1], "X" , Dim[2])
})
}
ui.r
shinyUI(fluidPage(
tags$button(
id = "reset_button",
class="btn action-button",
icon("close")
),
bsModal("CustomDataFilter","Settings","go_CustomDataFilter_Settings",size="small",
# radioButtons("Less_Than_Greater_Than","Less Than or Greater Than",choices=c("Less Than","Greater Than"),selected="Less Than",inline = TRUE),
uiOutput("FilterDataSettings"),
textOutput("result")
),
tabsetPanel(
tabPanel("Data",
titlePanel("Custom Data Filter"),
sidebarLayout(
sidebarPanel(
fileInput('datafile', h4('Import File'),
accept=c('text/csv', 'text/comma-separated-values,text/plain')),
actionButton("data_import","Import")
),
mainPanel(
DT::dataTableOutput("show_data")
)
)
),
tabPanel("Filter",
sidebarLayout(
sidebarPanel(
uiOutput("showDataDimensions.FilterData")
),
mainPanel(
DT::dataTableOutput("data"),
actionButton("addnewRow"," Add New Filter "),
actionButton("applyFilter"," Apply Filter to Data ")
)
)
)
)
)
)
Thank you for going through the code and appreciate your response.
Good morning,
in my dashboard I inserted a checkbox to select one or more output to display. In the ui I entered the checkbox and in the server all the conditions (if ... else if ...). When I launch the app it only shows me a plot, even when I select more than one choice in the checkbox. In addition it gives me this error in console:
"Warning in if (input$checkGroup == 1) { :the condition has length > 1 and only the first element will be used"
I suppose it's telling me that I can't handle more than one choice, how do I view all the plots I choose?
ui <- fluidPage(titlePanel("IULM Dashboard"), sidebarLayout(sidebarPanel(
selectInput("selection", "Choose a Dataset:",
choices = datasets),
("Barplot","Network",'Wordcloud', "LDA-Latent topic"),
#selected = "Barplot", inline = TRUE),
checkboxGroupInput("checkGroup", label = ("Checkbox group"),
choices = list("Barplot" = 1, "Network" = 2), selected = 1, inline = TRUE),
actionButton("update", "Change"))
, mainPanel(
uiOutput("plot")))
server <- function(input, output){
datasetInput <- reactive({
input$update
isolate({
withProgress({
setProgress(message = "Processing corpus...")
getTermMatrix(input$selection)
})
})
})
output$plot <- renderUI({
if(input$checkGroup== 1 ){
output$barplot <- renderPlot({
v=datasetInput()
dtm1 = removeSparseTerms(v, 0.992)
freq <- colSums(as.matrix(dtm1))
wf = data.frame(term = names(freq), occurrences = freq)
wf <- wf[order(wf$occurrences, decreasing = TRUE),]
wf2 = subset(wf[1:input$maxB,])
ggplot(wf2, aes(term, occurrences)) +
geom_bar(stat="identity", fill="darkred", colour="black", width=0.5)+
theme(axis.text.x=element_text(angle=45, hjust=1))+
ggtitle("Word barplot")})
plotOutput(outputId = "barplot", width = 600, height = 400)
}
else if(input$checkGroup== 2 ){
output$network <- renderPlot({
v=datasetInput()
dtm1 = removeSparseTerms(v, 0.992)
rowTotals <- apply(dtm1 , 1, sum)
dtm2 <- dtm1[rowTotals> 0, ]
wdtm <- weightTf(dtm2)
dtm1 <- removeSparseTerms(wdtm, 0.96)
dfm <- as.dfm(dtm1)
textplot_network(dfm, min_freq = 0.5, omit_isolated = TRUE,
edge_color = "#1F78B4", edge_alpha = 0.5, edge_size = 2,
vertex_color = "#4D4D4D", vertex_size = 2,
vertex_labelsize = 5, offset = NULL)})
plotOutput(outputId = "network", width = 600, height = 600)}
})
}
shinyApp(ui = ui, server = server)
You can try
library(shiny)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
checkboxGroupInput("variable", "Variables to show:",
c("Cylinders" = "cyl",
"Transmission" = "am",
"Gears" = "gear"))
),
mainPanel(
uiOutput("plots")
)))
server <- function(input, output) {
output$plots <- renderUI({
req(input$variable)
output = tagList()
if(any(input$variable %in% "cyl")){
tmp <- mtcars$cyl
output[[1]] <- renderPlot({plot(mtcars$mpg, tmp)})
}
if(any(input$variable %in% "am")){
tmp <- mtcars$am
output[[2]] <- renderPlot({boxplot(mtcars$mpg, tmp)})
}
output
})
}
shinyApp(ui = ui, server = server)
I am having trouble when initializing a shiny app in R. I would like eventReactive to trigger from any of several events, which are chained by reactive expressions. The app mostly works as intended, but does not display upon initialization and instead requires user to select an actionButton before results are displayed. Why is this?
I read documentation for eventReactive, played with ignoreNULL and ignoreInit settings, and done many online searches.
Example below.
require(shiny)
require(ggplot2)
ui <- fluidPage(
titlePanel("Car Weight"),
br(),
uiOutput(outputId = "cylinders"),
sidebarLayout(
mainPanel(
# plotOutput(outputId = "trend"),
# plotOutput(outputId = "hist"),
tableOutput("table"),
uiOutput(outputId = "dataFilter"),
actionButton(inputId = "update1", label = "Apply Filters"),
width = 9
),
sidebarPanel(
actionButton(inputId = "update2", label = "Apply Filters"),
uiOutput(outputId = "modelFilter"),
actionButton(inputId = "update3", label = "Apply Filters"),
width = 3
)
)
)
server <- function(input, output) {
# Read data. Real code will pull from database.
df <- mtcars
df$model <- row.names(df)
# Get cylinders
output$cylinders <- renderUI(
selectInput(
inputId = "cyl",
label = "Select Cylinders",
choices = c("", as.character(unique(df$cyl)))
)
)
# Subset data by cyl.
df2 <-
reactive(droplevels(df[df$cyl == input$cyl, ]))
# Filter data.
df3 <-
eventReactive({
##############################################################
# Help needed:
# Why does this block not update upon change in 'input$cyl'?
##############################################################
input$update1
input$update2
input$update3
input$cyl
},
{
req(input$modelFilter)
modelFilterDf <-
data.frame(model = input$modelFilter)
df3a <-
merge(df2(), modelFilterDf, by = "model")
df3a[df3a$wt >= input$dataFilter[1] &
df3a$wt <= input$dataFilter[2],]
},
ignoreNULL = FALSE,
ignoreInit = FALSE)
# Plot table.
output$table <- renderTable(df3())
# Filter by data value.
output$dataFilter <-
renderUI({
req(df2()$wt[1])
sliderInput(
inputId = "dataFilter",
label = "Filter by Weight (1000 lbs)",
min = floor(min(df2()$wt, na.rm = TRUE)),
max = ceiling(max(df2()$wt, na.rm = TRUE)),
value = c(
min(df2()$wt, na.rm = TRUE),
max(df2()$wt, na.rm = TRUE)
),
step = round(
max(df2()$wt, na.rm = TRUE) - min(df2()$wt, na.rm = TRUE)
) / 100,
round = round(log((
max(df2()$wt, na.rm = TRUE) - min(df2()$wt, na.rm = TRUE)
) / 100))
)
})
# Filter by lot / wafer.
output$modelFilter <- renderUI({
req(input$cyl)
checkboxGroupInput(
inputId = "modelFilter",
label = "Filter by Model",
choices = as.character(unique(df2()$model)),
selected = as.character(unique(df2()$model))
)
})
}
# Run shiny.
shinyApp(ui = ui, server = server)
I found a solution. Perhaps not the most elegant, but it works.
The problem was that input$modelFilter and input$modelFilter were one update behind df2. This did not matter when the user selected input$update, since df2 did not update, and only posed a problem during a newly created df2, since the filter would not match the data.
To resolve this, I added values <- reactiveValues(update = 0) which will increase by +1 every time df3 is created, and will reset back to 0 when a new df2 is created. If values$update > 0 then the data is filtered, otherwise, the unfiltered data is returned.
Possibly useful link: How can I set up triggers or execution order for eventReactive or ObserveEvent?
require(shiny)
require(ggplot2)
ui <- fluidPage(
titlePanel("Car Weight"),
br(),
uiOutput(outputId = "cylinders"),
sidebarLayout(
mainPanel(
tableOutput("table"),
uiOutput(outputId = "dataFilter"),
actionButton(inputId = "update1", label = "Apply Filters"),
width = 9
),
sidebarPanel(
actionButton(inputId = "update2", label = "Apply Filters"),
uiOutput(outputId = "modelFilter"),
actionButton(inputId = "update3", label = "Apply Filters"),
width = 3
)
)
)
server <- function(input, output) {
# Read data. Real code will pull from database.
df <- mtcars
df$model <- row.names(df)
df <- df[order(df$model), c(12,1,2,3,4,5,6,7,8,9,10,11)]
# Get cylinders
output$cylinders <- renderUI({
selectInput(
inputId = "cyl",
label = "Select Cylinders",
choices = c("", as.character(unique(df$cyl)))
)})
# Check if data frame has been updated.
values <- reactiveValues(update = 0)
# Subset data by cyl.
df2 <-
reactive({
values$update <- 0
df2 <- droplevels(df[df$cyl == input$cyl,])})
# Filter data.
df3 <-
eventReactive({
input$update1
input$update2
input$update3
df2()
},
{
if (values$update > 0) {
req(input$modelFilter)
modelFilterDf <-
data.frame(model = input$modelFilter)
df3a <-
merge(df2(), modelFilterDf, by = "model")
df3a <- df3a[df3a$wt >= input$dataFilter[1] &
df3a$wt <= input$dataFilter[2], ]
} else {
df3a <- df2()
}
values$update <- values$update + 1
df3a
},
ignoreNULL = FALSE,
ignoreInit = TRUE)
# Plot table.
output$table <- renderTable(df3())
# Filter by data value.
output$dataFilter <-
renderUI({
req(df2()$wt[1])
sliderInput(
inputId = "dataFilter",
label = "Filter by Weight (1000 lbs)",
min = floor(min(df2()$wt, na.rm = TRUE)),
max = ceiling(max(df2()$wt, na.rm = TRUE)),
value = c(floor(min(df2()$wt, na.rm = TRUE)),
ceiling(max(df2()$wt, na.rm = TRUE))),
step = round(max(df2()$wt, na.rm = TRUE) - min(df2()$wt, na.rm = TRUE)) / 100,
round = round(log((
max(df2()$wt, na.rm = TRUE) - min(df2()$wt, na.rm = TRUE)
) / 100))
)
})
# Filter by lot / wafer.
output$modelFilter <- renderUI({
req(input$cyl)
checkboxGroupInput(
inputId = "modelFilter",
label = "Filter by Model",
choices = as.character(unique(df2()$model)),
selected = as.character(unique(df2()$model))
)
})
}
# Run shiny.
shinyApp(ui = ui, server = server)