I am trying to add a second inputpanel in my shiny application which content depend on the input of the first inputpanel choice, I tried tout use condional panel with no luck.
ui.R
TO <- read.csv("~/TO/TO/TO.csv", sep=";")
library(shiny)
shinyUI(fluidPage(
# Application title
titlePanel("dasboard"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
selectInput("country", label = h4("Pays"),
choices = levels(as.factor(TO$Pays))),
conditionalPanel(
condition = "input.country == 'Allemagne'",
selectInput("to", label = h4("Tour opérateur"),
choices = levels(as.factor(as.character(TO[as.character(TO$Pays)=="Allemagne",]$TO))))),
conditionalPanel(
condition = "input.country == 'Angleterre'",
selectInput("to", label = h4("Tour Operator"),
choices = levels(as.factor(as.character(TO[as.character(TO$Pays)=="Angleterre",]$TO)))))
...
The solution that I found is to create a conditionalPanel for every value of the first inputPanel But is the second inputPanel output is only correct for the first value.
Does anyone have a solution?
I know the approach below is not via the conditional panels, as I think it would be simpler to do it via examples given below.
First you can use updateSelectInput to update your entries, something like this
rm(list = ls())
library(shiny)
runApp(list(
ui = bootstrapPage(
selectInput('data', 'Data', c('mtcars', 'iris')),
selectInput('Cols', 'Columns', "")
),
server = function(input, output, session){
outVar <- reactive({
mydata <- get(input$data)
names(mydata)
})
observe({
updateSelectInput(session, "Cols",choices = outVar()
)})
}
))
Other way you can use renderUI to create the selectInput and populate it like so:
rm(list = ls())
library(shiny)
runApp(list(
ui = bootstrapPage(
selectInput('data', 'Data', c('mtcars', 'iris')),
uiOutput('columns')
),
server = function(input, output){
output$columns <- renderUI({
mydata <- get(input$data)
selectInput('columns2', 'Columns', names(mydata))
})
}
))
Edit: how to add multiple widgets inside the renderUI
You need to wrap your divs inside the tagList() like so:
rm(list = ls())
library(shiny)
runApp(list(
ui = bootstrapPage(
selectInput('data', 'Data', c('mtcars', 'iris')),
uiOutput('columns')
),
server = function(input, output){
output$columns <- renderUI({
mydata <- get(input$data)
tagList(
selectInput('columns2', 'Columns', names(mydata)),
selectInput('columns3', 'Columns 2', names(mydata)))
})
}
))
Related
G'day awesome community
I am trying to make a dashboard of a dataframe that allows one to filter the dataframe by the levels within a column selected. This means a first pickerInput where the user selects the column, and then a second child pickerInput where the options are generated based on the column selected. I have figured out one way to make the pickerInputs dependent on each other, but for some reason when I try to apply the filtering, my dataframe has zero values and I cant see why?
Please see the reprex created with the mtcars dataset
library(shiny)
library(shinyWidgets)
library(dplyr)
library(DT)
data(mtcars)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(uiOutput('select_filter'),
uiOutput('filter')),
mainPanel(
dataTableOutput('table')
),
))
server <- function(input, output, session) {
data<-mtcars
categories<-c('cyl','vs','am','gear','carb')
output$select_filter <- renderUI({
pickerInput("select_filter", "Select flexi filter",
choices = levels(as.factor(categories))
)})
output$filter <- renderUI({
pickerInput("filter", "Flexi filter",
choices = unique(data[,input$select_filter]),
options = list('actions-box'=TRUE), multiple= TRUE,
selected = unique(data[,input$select_filter]))
})
filtered_data<-
#
reactive ({data %>% filter(input$select_filter %in% input$filter)
})
output$table<-renderDataTable(filtered_data())
}
shinyApp(ui, server)
Any help will be greatly appreciated! If any further information is required please let me know.
Cheers
In filter, use .data to get the column value using select_filter variable. Also included req so that it doesn't error out at the start when the input$select_filter is NULL.
filtered_data <-
reactive ({
req(input$select_filter)
data %>% filter(.data[[input$select_filter]] %in% input$filter)
})
Complete app code -
library(shiny)
library(shinyWidgets)
library(dplyr)
library(DT)
data(mtcars)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(uiOutput('select_filter'),
uiOutput('filter')),
mainPanel(
dataTableOutput('table')
),
))
server <- function(input, output, session) {
data<-mtcars
categories<-c('cyl','vs','am','gear','carb')
output$select_filter <- renderUI({
pickerInput("select_filter", "Select flexi filter",
choices = levels(as.factor(categories))
)})
output$filter <- renderUI({
pickerInput("filter", "Flexi filter",
choices = unique(data[,input$select_filter]),
options = list('actions-box'=TRUE), multiple= TRUE,
selected = unique(data[,input$select_filter]))
})
filtered_data<-
#
reactive ({
req(input$select_filter)
data %>% filter(.data[[input$select_filter]] %in% input$filter)
})
output$table<-renderDataTable(filtered_data())
}
shinyApp(ui, server)
Building on multiple stackoverflow questions, I tried to build this app which contains two action buttons the first one shows a data table the second one should open another sourced app but actually, nothing changes but in the global environment all list, functions, and dataframes are reflecting.
the used code.
#UI.R
library(shiny)
library(shinydashboardPlus)
library(DT)
library(readxl)
library(dplyr)
library(formattable)
library(shinydashboard)
library(shinyjqui)
library(shinyjs)
library(shinythemes)
library(markdown)
title <- "emblem"
ui = fluidPage(theme=shinytheme("superhero"),
dashboardPage(dashboardHeader(title = title, titleWidth = 200),
dashboardSidebar(selectInput("listofitems","Items List",c("Home","Group","Clients"), selected = "Home")),
dashboardBody(
useShinyjs(),
uiOutput("ui_myHome"))))
#SERVER.R
Clientsbutton<-fluidPage(theme=shinytheme("yeti"),
DT::dataTableOutput("mytable"))
shinyServer(function(input, output, session){
output$mytable = DT::renderDataTable({
mtcars
})
output$ui_myHome<-renderUI({
if (input$listofitems == 'Home'){(fluidPage(
widgetUserBox(title = "Clients",
shiny::actionButton(inputId='clientsmainbuttonId', label="Click here"),
type = 2, src = "https://adminlte.io/themes/AdminLTE/dist/img/user7-128x128.jpg", color = "yellow"),
widgetUserBox(title = "Group",
shiny::actionButton(inputId='GroupbuttonId', label="Click here"),
type = 2, src = "https://adminlte.io/themes/AdminLTE/dist/img/user7-128x128.jpg", color = "green")))}
else if (input$listofitems == 'Clients'){(Clientsbutton)}
else if (input$listofitems == 'Group'){(source("testsource.R",local = T)$value)}
})
observeEvent (input$GroupbuttonId,{
#browser
source("testsource.R",local = T)$value
})
observeEvent(input$clientsmainbuttonId,{updateSelectInput(session,"listofitems","Items List", choices =c("Home","Group","Clients"), selected = "Clients")},ignoreInit = TRUE)
observeEvent(input$logo,{updateSelectInput(session,"listofitems","Items List", choices =c("Home","Group","Clients"), selected = "Home")},ignoreInit = TRUE)
})
#TO BE SOURCED APP
File name testsource.R
rm(list = ls())
library(shiny)
shinyApp(
ui=shinyUI(basicPage(
actionButton("go", "Go"),
numericInput("n", "n", 50),
plotOutput("plot")
)),
server=shinyServer(function(input, output, session){
randomVals <- eventReactive(input$go, {
runif(input$n)
})
output$plot <- renderPlot({
hist(randomVals())
})
})
)
I'm trying to create the scenario whereby using conditionalpanel, I am able to have an user input of checked boxes to display either 1 or 2 plots, one after another.
My reproducible code can be found below, however, I am unable to display the plots.
Could someone please share with me where did I make a mistake?
library(shiny)
ui = fluidPage(
titlePanel("Plot1 or Plot2?"),
sidebarLayout(
sidebarPanel(
checkboxGroupInput("my_choices", "Plot1 or Plot2",choices = c("Plot1", "Plot2"), selected = "Plot1"),width=2),
mainPanel(
conditionalPanel(
condition = "input.my_choices == 'Plot1'",
plotOutput("plot1")
),
conditionalPanel(
condition = "input.my_choices == 'Plot2'",
plotOutput("plot2")
),
conditionalPanel(
condition = "input.my_choices.includes('Plot1', 'Plot2')",
plotOutput("plot1"),
plotOutput("plot2")
)
)
)
)
server = function(input, output) {
output$plot1 <- renderPlot({plot(iris)})
output$plot2 <- renderPlot({plot(mtcars)})
}
shinyApp(ui, server)
Update:
I've got what I wanted but without using ConditionalPanel function. Here's the code below:
Would appreciate if someone can share with me the proper way of using ConditionalPanel Function! (:
library(shiny)
#data
df <- iris
#ui
ui <- fluidPage(
sidebarPanel(
checkboxGroupInput(inputId = "Question",
label = "Choose the plots",
choices = c("Plot1", "Plot2", "Plot3"),
selected = "")),
mainPanel(
uiOutput('ui_plot')
)
)
#server
server <- function(input, output)
{
# gen plot containers
output$ui_plot <- renderUI({
out <- list()
if (length(input$Question)==0){return(NULL)}
for (i in 1:length(input$Question)){
out[[i]] <- plotOutput(outputId = paste0("plot",i))
}
return(out)
})
# render plots
observe({
for (i in 1:3){
local({ #because expressions are evaluated at app init
ii <- i
output[[paste0('plot',ii)]] <- renderPlot({
if ( length(input$Question) > ii-1 ){
return(plot(runif(100)))
}
NULL
})
})
}
})
}
shinyApp(ui, server)
I would give you an alternative as you will need to create new plots with different id in order for that to work. The simplest one I can think of is using shinyjs package and its hide and show functions. You can also do this via renderUI but you shouldn't give unnecessary work to your server only if you're showing and hiding the elements
library(shiny)
library(shinyjs)
ui = fluidPage(
useShinyjs(),
titlePanel("Plot1 or Plot2?"),
sidebarLayout(
sidebarPanel(
checkboxGroupInput("my_choices", "Plot1 or Plot2",choices = c("Plot1", "Plot2"), selected = "Plot1"),width=2),
mainPanel(
plotOutput("plot1"),
plotOutput("plot2")
)
)
)
server = function(input, output,session) {
# hide plots on start
hide("plot1");hide("plot2")
output$plot1 <- renderPlot({plot(iris)})
output$plot2 <- renderPlot({plot(mtcars)})
observeEvent(input$my_choices,{
if(is.null(input$my_choices)){
hide("plot1"); hide("plot2")
}
else if(length(input$my_choices) == 1){
if(input$my_choices == "Plot1"){
show("plot1");hide("plot2")
}
if(input$my_choices == "Plot2"){
hide("plot1");show("plot2")
}
}
else{
if(all(c("Plot1","Plot2") %in% input$my_choices)){
show("plot1");show("plot2")
}
}
},ignoreNULL = F)
}
shinyApp(ui, server)
I have a simple shiny app in which I use a numericInput() "tests" to add rows to the dataframe. Then I give the names of the "Label" column as choices to the selectInput() "Label2". The problem is that when I edit the names in column "Label" of the table the selectInput() choices are not updated accordingly. For example if I rename "Test 1" to "Test A" in the table I want it to change in the selectInput() as well.
#ui.r
library(shiny)
library(rhandsontable)
ui <- navbarPage(
"Application",
tabPanel("General",
sidebarLayout(
sidebarPanel(
uiOutput("tex2")
),
mainPanel(
rHandsontableOutput("hot3"),
uiOutput("book12")
)
)))
#server.r
server <- function(input, output,session) {
output$tex2<-renderUI({
numericInput("text2", "#tests", value = 1, min=1)
})
output$book12<-renderUI({
selectInput("bk12",
"Label2",
choices=(rt4()$Label))
})
rt4<-reactive({
DF <- data.frame(
Label=paste("Test",1:input$text2),
stringsAsFactors = FALSE)
})
output$hot3 <-renderRHandsontable(
rhandsontable(rt4())
)
}
This seems to work. You were not reading back the edited rhandsontable
in your code.
So i ve added an observe to do this
observe({
if(!is.null(input$hot3))
rt4$DF <- hot_to_r(input$hot3)
})
Also in the code, Ive added some req statements to check for NULL conditions at the time of initialisation, you can use the if..else mechanism that you have used in some of your other questions too.
#ui.r
library(shiny)
library(rhandsontable)
ui <- navbarPage(
"Application",
tabPanel("General",
sidebarLayout(
sidebarPanel(
uiOutput("tex2")
),
mainPanel(
rHandsontableOutput("hot3"),
uiOutput("book12")
)
)))
#server.r
server <- function(input, output,session) {
rt4<- reactiveValues()
output$tex2<-renderUI({
numericInput("text2", "#tests", value = 1, min=1)
})
output$book12<-renderUI({
selectInput("bk12",
"Label2",
choices=(rt4$DF$Label))
})
observe({
req(input$text2)
rt4$DF <- data.frame(
Test=paste(1:input$text2),
Label=paste("Test",1:isolate(input$text2)),
stringsAsFactors = FALSE)
})
output$hot3 <-renderRHandsontable({
req(input$text2)
rhandsontable(rt4$DF)
} )
observe({
if(!is.null(input$hot3))
rt4$DF <- hot_to_r(input$hot3)
})
}
shinyApp(ui,server)
I am using R shiny to develop a interactive analysis tool. Now I want to do classification tree based on variables check in checkboxGroupInput. How can I select that subset of data? THX!
UI:
dateInput("date","Enter date:",value = date),
checkboxGroupInput("variable", "Variable:",
choices = names ,selected = names
)
server I tried, but doesn't work:
dataall <- reactive({
filename <- paste0("dataall_'", input$date, "'.RData")
load(filename)
feature.test[,names(feature.test) %in% input$variable]
})
feature.test is data in loaded file.
Hard to understand what you want since you don't subset the file you load. What is feature.test ?
Here is a simple example to how to subset a data frame using an input and shiny reactivity :
shiny::runApp(list(
ui = basicPage(
selectInput("specy", "Specy", choices = levels(iris$Species)),
tableOutput("content")
),
server = function(input, output, session) {
output$content <- renderTable({
iris[iris$Species == input$specy, ]
})
}
))
EDIT ## :
Subset by column :
shiny::runApp(list(
ui = pageWithSidebar(
headerPanel("Example"),
sidebarPanel(
checkboxGroupInput("variable", "Variable:", choices = names(iris))
),
mainPanel(
tableOutput("content")
)
),
server = function(input, output, session) {
output$content <- renderTable({
if(is.null(input$variable))
return()
iris[input$variable]
})
}
))
"variable" is supposed to be "date" since this is the control that you are referencing in the UI part, as in:
checkboxGroupInput( "date", "Variable:",
choices = names ,selected = names
)
For data.table you need to add a ,with=FALSE or use a temporary variable in the server code:
# Load libraries
library(shiny)
library(data.table)
# Copy dataset
irisDT=copy(iris)
setDT(irisDT)
# Shiny app
shiny::runApp(list(
# UI
ui = pageWithSidebar(
headerPanel("Example"),
sidebarPanel(
checkboxGroupInput("variable", "Variable:", choices = names(iris))
),
mainPanel(
tableOutput("content")
)
),
# Server
server = function(input, output, session) {
output$content <- renderTable({
if(is.null(input$variable))
return()
# iris[input$variable] # data.frame
irisDT[, input$variable, with=FALSE] # data.table
# Alternatively:
# tmp <- input$variable
# irisDT[, ..tmp]
})
}
))