R Shiny - how to put value and name attributes in checkboxInput? - r

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 = ", ")))
})
}
))

Related

Shiny: updateSelectInput() selected argument issue with observe()

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.

Using InsertUI and UpdateSelectizeInput

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.

R Shiny: Make radiobuttons impacts other input

I am making something i Shiny and am wondering whether it is possible to make radiobuttons decide another input.
A toy example that replicates my problem is given by:
if (interactive()) {
ui <- fluidPage(
radioButtons("dist", "Distribution type:",
c("Normal" = "norm",
"Uniform" = "unif")),
textInput(inputId = "textid", label = "Text input-header", value = "rnorm"),
plotOutput("distPlot")
)
server <- function(input, output) {
df <- reactive({
switch(input$textid,
rnorm = {rnorm(500)},
uni = {runif(500)},
exp = {rexp(500)},
)})
output$distPlot <- renderPlot(hist(df())
)
}
shinyApp(ui, server)
}
As it is now, it is the input in the text box that decides what kind of distribution, that is used to generate the data. What I would like is that when one clicks of one of the radio buttons then the text is updated in the text box (e.g. if "Uniform" is checked off, then the textunput is updated with "uni" - and thereby this distribution is used). The thing is that I need the box since I would like to be able to choose somethiong that is not an option among the radio buttons (so it does not work for me just to add extra radio buttons). The extra option in this case is, that one can write "exp" in the text input (this distribution cannot be chosen from a radio button).
It might seem a bit idiotic in this example, but in my case I have 2 very often used timestamps, but the app must allow the user to choose every possible date as well.
Is this somehow possible?
Thanks in advance!
Something like this? Note that I added the req where it is required to have your text input as one of "rnorm","uni","exp"
library(shiny)
if (interactive()) {
ui <- fluidPage(
radioButtons("dist", "Distribution type:",c("Normal" = "rnorm","Uniform" = "uni","Exponential" = "exp")),
textInput(inputId = "textid", label = "Text input-header", value = "rnorm"),
plotOutput("distPlot")
)
server <- function(input, output,session) {
observeEvent(input$dist,{
updateTextInput(session, "textid",label = "Text input-header",value = input$dist)
})
df <- eventReactive(input$textid,{
req(input$textid %in%c("rnorm","uni","exp"))
switch(input$textid, rnorm = {rnorm(500)},uni = {runif(500)}, exp = {rexp(500)},
)})
output$distPlot <- renderPlot(hist(df()))
}
shinyApp(ui, server)
}

Shiny R: Populate a list from input and return list on output via reactive

I try to populate a list on shiny with the elements of the list passed over from a shiny input. The list should accumulate all the made choices. The list should finally be sent to the shiny output. Actually I already get a list which I can send to output. This list is however always just of length one and this single element gets updated as the input does. Actually I am only interested in the "names" of the list, this is why I assign the value 1 to each name element:
UI.R
shinyUI(
fluidRow(
column(1,
# reactive input
selectInput("Input1",
label = "Select Parameter 1",
choices = c("none",letters[1:16]),
multiple = T),
selectInput("Input2",
label = "Select Parameter 2",
choices = c("none",c(1:24) )
multiple = T),
# printout of list
htmlOutput("printoutList")
) # end of column
) # end of fluid row
) # end of Shiny UI
Shiny.R
# create an empty list
container <- list()
shinyServer(function(input, output) {
# pass over input to reactive
inputInfo <- reactive({
if(input$Input1 == "none" | input$Input2 == "none") {
"-"
} else {
paste(input$Input1 ,input$Input2, sep = "")
}
})
# fill list and pass over list to output
output$printoutList <- renderUI({
container[[inputInfo()]] <- 1
paste("You have chosen: ", names(container), sep = "")
})
)} #end of shinyServer function
Any idea how to solve this? I already tried around a lot... unfortunately I am quite new to R, especially to shiny ! I would really appreciate any kind of help! Thanks !
include the multiple = TRUE argument for selectInput
selectInput("Input1",
label = "Select Parameter 1",
choices = c("none",letters[1:16]),
multiple = TRUE
)
But also it seems like your server and ui files are mixed up and you don't have the shinyServer function in the code.

Force no default selection in selectInput()

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
})

Resources