The Shiny documentation mentions that for selectInput():
selected The value (or, if none was supplied, the title) of the navigation item that should be selected by default. If NULL, the first navigation will be selected.
What if by default I don't want to select any value from select list?
Actually my select value is getting selected by default and rest part of app is getting executed automatically. But I don't want to select any value initially. What should I supply to the selected argument in selectInput() to do that?
Indeed, I don't want anything to be selected automatically. I used the code below but still it's selecting first available value from the list. I want there to be no selection by default, so the user can then select any option.
output$Choose_App <- renderUI({
selectInput("app",
"Select App:",
choices = as.character(mtrl_name),
selected = NULL ,
multiple = FALSE
)
})
Going through the documentation I noticed that the selection can be empty only if I select multiple=TRUE. Is this correct?
When I changed to multiple=TRUE, then it it's not getting selected by default, which is what I want. But unfortunately before making any selection I am also getting following error message:
ERROR: bad 'file' argument
Does anybody know about this if I am doing something wrong? But if I select this file then error is gone.
I am using following code for this:
# server.R
setwd("/opt/shiny-server/samples/sample-apps/P-Dict_RDS2")
mtrl_name <- try(system("ls | grep -i .rds", intern = TRUE))
shinyServer(function(input, output) {
# First UI input (Service column) filter clientData
output$Choose_Molecule <- renderUI({
selectInput("molecule",
"Select Molecule:",
choices = as.character(mtrl_name),
selected = input$molecule,
multiple = TRUE
)
})
You can use the selectize input instead of the select input, with some custom selectize options to set the initial selection to be empty. An example has been provided in the Shiny Gallery. In particular, see the example #6.
# make sure you have shiny >= 0.9.1
selectizeInput(
'e6', '6. Placeholder', choices = state.name,
options = list(
placeholder = 'Please select an option below',
onInitialize = I('function() { this.setValue(""); }')
)
)
BTW, for the error "ERROR: bad 'file' argument", I do not think anybody can help you without seeing the source code of your app, and it may be a separate question.
Faced a similar issue. The solution I found is based of #MKa's answer. You do not want to set multiple=T if your code can't handle multiple values. What I suggest is:
selectInput("molecule",
"Select Molecule:",
choices = c("",as.character(mtrl_name)),
selected = NULL,
multiple = F
)
And to retrieve the value selected:
if(!is.null(input$molecule))
{
if(nchar(input$molecule)>1)
{
#do your thing..
}
}
Fixed my problem. Let me know if you found a better solution.
I think you can get around it by adding an empty string to your choice list:
selectInput("app",
"Select App:",
choices = c("", as.character(mtrl_name)),
selected = NULL,
multiple = FALSE)
#Yihui Xie's answer requires selectInput(..., selectize = TRUE). If you want selectize = FALSE, you can still achieve a similar effect as follows.
This is not documented:
selected The initially selected value (or multiple values if multiple = TRUE). If not specified then defaults to the first value for single-select lists and no values for multiple select lists.
But for single-select lists if you can use selectize = FALSE, size = 4 (any non-NULL size would work), then you can set selected = FALSE to force no default selection.
library(shiny)
# Define UI for application that draws a histogram
ui <- fluidPage(
mainPanel(
uiOutput("Choose_Molecule")
)
)
# Define server logic required to draw a histogram
server <- function(input, output) {
# First UI input (Service column) filter clientData
output$Choose_Molecule <- renderUI({
selectInput("molecule",
"Select Molecule:",
choices = rownames(mtcars),
selected = FALSE,
multiple = FALSE
, selectize = FALSE, size = 4 ##needed for `selected = FALSE` to work
)
})
}
# Run the application
shinyApp(ui = ui, server = server)
A cleaner solution is to use selectizeInput, allow multiple selections, but then limit the maximum number of selections to 1. This means the default selection will be NULL, the user can only select 1 option, and you don't have to add an empty string to your choices or similar workarounds previously listed here.
selectizeInput(
"tag",
"Label",
choices = choices,
multiple = TRUE,
options = list(maxItems = 1)
)
A workaround would be to use updateSelectInput. The point here is that you set your selected = argument to length(your_vector_with_choices).
You can create a reactiveValues if you want your selectInput to be updated at the very beginning (in that case only observed at program start).
library(shiny)
shinyApp(
ui = fluidPage(
selectInput("state", "Choose a state:", NULL),
textOutput("result")
),
server = function(input, output, session) {
values <- reactiveValues(start = NULL)
observe({
choiceList <- list(`East Coast` = list("NY", "NJ", "CT"),
`West Coast` = list("WA", "OR", "CA"),
`Midwest` = list("MN", "WI", "IA"))
updateSelectInput(session, "state", choices = choiceList, selected = choiceList[length(choiceList)])
})
output$result <- renderText({
paste("You chose", input$state)
})
}
)
Answering after 6 years, as I got the same error now. We can write
selected = character(0)
to force not selecting any user input.
A modification of #rookieJoe answer is to use req() instead of the ifs. Read this page for an intro to the req() usage (in this specific question, the fact that req() takes the string "" as a "falsy" value).
For example, if the selectInput is like his:
selectInput("molecule",
"Select Molecule:",
choices = c("", as.character(mtrl_name)),
selected = NULL,
multiple = F
)
To retrive the value in a reactive as:
my_reactive <- reactive({
req(input$molecule)
# do your stuff
})
Related
I'm using observe() to change a value of a selectInput after a user selects TRUE/FALSE in the Categorical drop down list. In the first tab of my program if you set Categorical to TRUE then Impute gets updated to mode and mean otherwise. I'm then able to change the Impute value as desired without it reverting to the value that appears when TRUE/FALSE is selected.
In the second tab I have a multiple selectInput list with a similar interface as the first tab; the interface is created for every value selected in Select covariates. In this section I also used observe() to update each selected covariates' Impute drop down list accordingly to the logic of the first tab (i.e. if TRUE is selected then Impute gets updated to mode and mean otherwise). However, the value in Impute appers to be locked in the sense that I'm not able to switch between values as I did in the first tab.
I don't know how to correct this issue and I was wondering if anyone out there has encountered this similar problem and has been able to fix it. Any advice or help would be greatly appreciated.
The code to my app can be seen below and can be ran in a single file.
library(shiny)
library(shinyjs)
ui <- shinyUI(fluidPage(
shinyjs::useShinyjs(),
navbarPage("Test",id="navbarPage",
tabPanel("First tab", id = "first_tab",
sidebarLayout(
sidebarPanel(
selectInput('covariate.L.categorical', 'Categorical', c("",TRUE,FALSE)),
selectInput('covariate.L.impute', "Impute", c("","default","mean","mode","median"))
),
mainPanel()
)
),
tabPanel("Second tab", id = "second_tab",
sidebarLayout(
sidebarPanel(
selectInput('covariates', 'Select covariates', choices = c("age","sex","race","bmi"), multiple=TRUE, selectize=TRUE),
tags$hr(),
uiOutput("covariateop")
),
mainPanel()
)
))
))
server <- shinyServer(function(input, output, session) {
rv <- reactiveValues(cov.selected = NULL)
observe({
updateSelectInput(session, "covariate.L.impute", selected = ifelse(input$covariate.L.categorical,"mode","mean"))
})
output$covariateop <- renderUI({
lapply(input$covariates, function(x){
tags$div(id = paste0("extra_criteria_for_", x),
h4(x),
selectInput(paste0(x,"_categorical"), "Categorical",
choices = c("",TRUE,FALSE)),
selectInput(paste0(x,"_impute"), "Impute",
choices = c("","default","mean","mode","median")),
textInput(paste0(x,"_impute_default_level"), "Impute default level"),
tags$hr()
)
})
})
observe({
lapply(input$covariates, function(x){
updateSelectInput(session, paste0(x,"_impute"), selected = ifelse(as.logical(reactiveValuesToList(input)[[paste0(x,"_categorical")]])==TRUE,"mode","mean"))
})
})
})
# Run the application
shinyApp(ui = ui, server = server)
In your observe in the second tab, you use reactiveValuesToList(input)[[paste0(x,"_categorical")]]. This means that this observe is reactive to any changes in any input element, so also if you change the "Imputation" input. You can just use input[[paste0(x,"_categorical")]] instead to get rid of this behaviour.
Note that the implementation of dynamic UI with lapply leads to the deletion and anew rendering of already existing input selections when an additional variable is selected. Maybe you can have a look at insertUI/removeUI to get a bit nicer UI.
I'm attempting to use InsertUI and updateSelectizeInput methods in the server function as part of my app, primarily since my list of choices is so large.
library(shiny)
baby_names <- babynames::babynames %>%
distinct(name) %>%
.[["name"]] %>%
sort()
ui <- fluidPage(
tags$div(id = 'placeholder')
)
server <- function(input, output, session) {
id = "babies"
insertUI(selector = '#placeholder',
ui = tags$div(list(
selectizeInput("babynames", label = "Baby Names!", multiple = TRUE, choices = NULL, width = '400px',
options = list(placeholder = 'Type a baby name.'))
),
immediate = TRUE,
id = id))
updateSelectizeInput(
session, inputId = "babynames",
choices = baby_names,
server = TRUE)
}
shinyApp(ui, server)
I'm not getting much success out of this, as the selectizeInput is displayed but the dropdown options are not shown. How should I address this issue? Thanks!
This is explained in the documentation of insertUI:
This function allows you to dynamically add an arbitrarily large UI object into your app, whenever you want, as many times as you want. Unlike renderUI(), the UI generated with insertUI is not updatable as a whole: once it's created, it stays there. Each new call to insertUI creates more UI objects, in addition to the ones already there (all independent from one another). To update a part of the UI (ex: an input object), you must use the appropriate render function or a customized reactive function
(I added the bold font)
Therefore, you should use renderUI instead.
I'm working with shiny and I'm having difficulty having R recognize input when using conditionalPanel. I have two such panels in my app because I need them to produce a certain list depending on which of the radio buttons a user selects.
Everything is rendered fine from the UI perspective, but for some reason R is unable to pick up any input when the 'Name' option is passed through the conditional panel, even if an item is entered in the field. The correct list is used, but for some reason it doesn't detect any input. Here's a screenshot of the selections and results.
I have no issues if I choose the other option from within the radio buttons and enter an item--it works as expected. Here's the code I'm working with.
ui <- fluidPage(
sidebarPanel(
# the user can choose from two options within the radio buttons
radioButtons("items_type", label = "Choose items for analysis"
, choices = list("Items - Item number & name" = "Both", "Items - Item name only" = "Name")
, selected = "Both")
# if the 'Both' option is selected, the items_list_names_id option is used
, conditionalPanel(
condition = "output.items_type == 'Both'"
, selectInput("items", label = NULL, choices = items_list_names_id, multiple = TRUE))
# if the 'Name' option is selected, the items_list_names option is used. input
# is not being detected here for some reason, and I'm wondering if it's because
# I use "items" for both selectInputs
, conditionalPanel(
condition = "output.items_type == 'Name'"
, selectInput("items", label = NULL, choices = items_list_names, multiple = TRUE))
# action button so the user can submit for analysis based on their selected options
, actionButton("go", "Run", style = "color: white; background-color: #2759aa")
)
)
server <- function(input, output){
# this portion is used to detect if the user alternates between either option from the radio buttons and uses the appropriate selectInput option
output$items_type <- reactive({
input$items_type
})
outputOptions(output, "items_type", suspendWhenHidden = FALSE)
Results <- eventReactive(input$go, {
# this portion is simply for testing for me to see how R recognizes the inputs
observe({print(input$items_type)})
observe({print(input$items)})
# checks to make sure the user selects at least 1 item. For some reason,
# this portion is triggered when at least 1 item is selected under the 'Name'
# condition from the conditional panel.
validate(
need(input$items > 0, 'Please select at least 1 item for analysis')
)
#other steps start here, but the above is the more pertinent part
}
EDIT: So it looks like having the same input id for both selectInput options is what's causing R to not recognize the input when it switches between the conditional panels. However, it would be ideal to have one input id because intput$item is used in other portions of my code not shown above. Rewriting the code so that it would use two variables, input$item1 and input$item2 for example, for each condition would be potentially very troublesome. I'm open to any suggestions to avoid this.
EDIT 2: I was thinking maybe using a single conditonalPanel and using a switch statement to alternate between the two lists depending on the user's selection. This should work, theoretically, and would be a convenient solution without modifying all of my other code. It looks like this:
, conditionalPanel(
condition = "output.items_list_selection"
, selectInput("items", label = 'Select items'
, choices = switch("output.items_list_selection", "Both" = items_list_names_id, "Name" = items_list_names)
, multiple = TRUE))
But a drop down menu doesn't appear as it's supposed to with this revision.
A possible solution is to use updateSelectInput , so there is no problem with two id having the samedi inputId
library(shiny)
items_list_names_id = c("id1", "id2")
items_list_names = c('name1', 'name2')
ui <- fluidPage(
sidebarPanel(
# the user can choose from two options within the radio buttons
radioButtons("items_type", label = "Choose items for analysis"
, choices = list("Items - Item number & name" = "Both", "Items - Item name only" = "Name")
, selected = "Both"),
# if the 'Both' option is selected, the items_list_names_id option is used
selectInput("items", label = NULL, choices = c('init'), multiple = TRUE),
# action button so the user can submit for analysis based on their selected options
actionButton("go", "Run", style = "color: white; background-color: #2759aa")
)
)
server <- function(input, output, session){
# change the choices depending on the value of input$intems_type
observeEvent(input$items_type, {
if(input$items_type == 'Both'){
updateSelectInput(session, 'items', label = NULL, choices = items_list_names)
}
if(input$items_type == 'Name'){
updateSelectInput(session, 'items', label = NULL, choices = items_list_names_id)
}
})
# check if it's working
observeEvent(input$go,{
print(input$items)
print(input$items_type)
})
}
shinyApp(ui, server)
I am building an Rshiny dashboard and am working to integrate some of shiny's more interactive features, and am currently working with the renderUI function, which (should, I believe) create additional widgets / input parameters based on the value of another input parameter. I am running into a simple error, but am having difficulty debugging. Below is a demo with the relevant code:
choices = c('All', 'None')
names(choices) = choices
ui <- fluidPage(theme = shinytheme('united'),
# create permanent input for shot chart type (should be 5 options)
selectInput(inputId = 'choice.input', label = 'Select a choice', multiple = FALSE,
choices = choices, selected = 'All'),
uiOutput('secondinput')
)
server <- shinyServer(function(input, output) {
if(input$choice.input == 'All') {
my.second.input <- c('a', 'b', 'c', 'd', 'e')
names(my.second.input) <- my.second.input
# player parameter for player whose shot chart will be shown
output$secondinput <- renderUI({
selectInput(inputId = 'another.input', label = 'Check this input', multiple = FALSE,
choices = my.second.input, selected = 'a')
})
}
})
shinyApp(ui, server)
I'm not sure what's wrong here - I thought my use of renderUI() in the server function, with the names matching (output$secondinput, uiOutput('secondinput')), was corrent, but this is throwing an error at me...
Note that my full code has several options for choice.input, and I would like to have an if() case in the server for each of the (4-5) choice.input() values. Any help with what's wrong here is appreciated, thanks!
EDIT - to clarify, the select input choice.input, with label 'Select a Choice', should be displaying always. When this input is set to 'All', then I'd like for an additional input, secondinput, to be displayed. If choice.input is not set to 'All', then I don't want the second input to be displayed. Hope this helps.
Here's a version of your code that works. I'm not sure if this is exactly what you want, it was a bit hard to tell, but hopefully you can take it from there.
choices = c('All', 'None')
names(choices) = choices
ui <- fluidPage(
# create permanent input for shot chart type (should be 5 options)
selectInput(inputId = 'choice.input', label = 'Select a choice', multiple = FALSE,
choices = choices, selected = 'All'),
uiOutput('secondinput')
)
server <- shinyServer(function(input, output) {
# player parameter for player whose shot chart will be shown
output$secondinput <- renderUI({
if(input$choice.input == 'All') {
my.second.input <- c('a', 'b', 'c', 'd', 'e')
names(my.second.input) <- my.second.input
selectInput(inputId = 'another.input', label = 'Check this input', multiple = FALSE,
choices = my.second.input, selected = 'a')
} else{
return(NULL)
}
})
})
shinyApp(ui, server)
The error that happened told you that you're trying to access a reactive value without a reactive context. You were trying to access the input value (which is reactive) outside of a render function or an observe function, which are reactive contexts.
If you don't understand what that means, I highly suggest you read this section on a shiny tutorial I wrote, reactivity 101.
The second issue here was that you were trying to "nest" a render function, which can work but is the wrong way to think about it, and suggests that you may not really grasp the concept of reactivity and render functions fully. Notice that I moved the render function to the outside, that's generally the correct way to program in shiny. If you have a bit of time, I suggest watching Joe Cheng's (the author of shiny) videos "effective reactive programming I and II" from the 2016 shiny conference https://www.rstudio.com/resources/webinars/shiny-developer-conference/
I find RShiny is quite difficult to use as I can't have the control over my html, for instance,
I want to create a check box below,
<input type="checkbox" id="species" name="species_particles" value="particles"/>
in my shiny ui.R,
checkboxInput(inputId = "species",
label = "Particles",
value = "particles")
I get this error,
ERROR: invalid 'y' type in 'x && y'
I don't know what it means and how to fix it. And it does not make sense. what y? what x?
what about the name attribute? how can I put that in checkboxInput()?
The argument to value needs to be logical and determines whether the checkbox is selected by default or not. For example,
checkboxInput(inputId = "species",
label = "Particles",
value = TRUE)
See ?checkboxInput for details.
The thread is somewhat older, but as no answer has been accepted yet, in order to assign values to the checkboxes, simply use checkboxGroupInput instead of checkboxInput.
library("shiny")
runApp(list(
## ui.R
ui = shinyUI(
fluidPage(
checkboxGroupInput(
inputId = "species"
, label = "Particeles"
, choices = c("Quarks" = "Quarks", "Leptons" = "Leptons"
, "Antiquarks" = "Antileptons"))
, uiOutput("tmp")
)
)
## server.R
, server = function (input, output, session) {
output$tmp <- renderUI({
HTML(paste("Currently selected:",
paste(input$species, collapse = ", ")))
})
}
))