How to get the drop box empty at the start in shiny - r

I use drop box to display three options,
selectInput("select", label = h5("Choose Annotation DB"),
choices = list("h10kcod.db"="h10kcod","h20kcod.db"="h20kcod","hwgcod.db"="hwgcod")),
selected = NULL)
But it always have the first choice in the drop box already selected, however i am interested to get the drop box empty(with no one selected). How should i do that. Thanks

Hello look at this example :
library("shiny")
ui = fluidPage(
# method 1 : put an empty element "" in your list
selectInput("select", label = h5("Choose Annotation DB"),
choices = list("", "h10kcod.db"="h10kcod","h20kcod.db"="h20kcod","hwgcod.db"="hwgcod")),
# method 2 : use selectizeInput and the placeholder option
selectizeInput("select", label = h5("Choose Annotation DB"),
choices = list("h10kcod.db"="h10kcod","h20kcod.db"="h20kcod","hwgcod.db"="hwgcod"),
options = list(placeholder = 'A placeholder',
onInitialize = I('function() { this.setValue(""); }')))
)
server = function(input, output) {
}
shinyApp(ui = ui, server = server)

Related

How do I use input from `selectizeInput` to filter a list of options and then `updateSelectizeInput`?

BACKGROUND:
I have a large list of stock symbols, 27,000 rows, that I would like to be choices in a selectizeInput() on a shinyApp. Since the list is large I am using server = T in updateSelectizeInput().
AIM:
I would like the options list to not load/render until a user starts typing a string into selectizeInput(), so that I can return all symbols that start with that letter, to reduce loading all 27,000 rows in the input. I would like input$ticker to be what is observed and then what triggers the filtering code logic. How can i achieve this without using a specific button?
Shown below is
intended output, but with a button to produce the behavior instead of the user being in the text box. This is along the lines of what I would like, but does not automatically start searchign when I type in the box and has bad code smell to me.
current logic, using input$ticker in an observer to trigger selection of df and populate updateSelectize() with new choices, but is failing and the app is evaluating too soon?\
trying to load choices once, using upload button only doesn't work
REPREX:
1.
library(shiny)
tickers <- rep(rownames(mtcars), 850)
ui <- {
renderUI(
shiny::fluidRow(
bs4Dash::box(
title = shiny::selectizeInput(
inputId = "ticker",
label = "Ticker:",
choices = NULL,
selected = "AAPL",
options = list(
placeholder = "e.g AAPL",
create = TRUE,
maxOptions = 50L
)
),
actionButton(
inputId = "update",
label = "UPDATE NOW"
),
id = "tickerBox",
closable = F,
maximizable = F,
width = 12,
height = "250px",
solidHeader = FALSE,
collapsible = F
)
)
)
}
server <- function(input, output, session){
choice <- reactive(
tickers[startsWith(tickers$symbol, input$ticker), ]
)
observeEvent(input$update, {
updateSelectizeInput(
session = session,
label = "Ticker:",
inputId ="ticker",
choices = choice(),
server = TRUE
)
})
}
shiny::shinyApp(ui = ui, server = server)
# REPREX for selectize, glitches and `input$ticker` observer causes loop gltich?
library(shiny)
tickers <- rep(rownames(mtcars), 850)
ui <- {
renderUI(
shiny::fluidRow(
bs4Dash::box(
title = shiny::selectizeInput(
inputId = "ticker",
label = "Ticker:",
choices = NULL,
selected = "AAPL",
options = list(
placeholder = "e.g AAPL",
create = TRUE,
maxOptions = 50L
)
),
actionButton(
inputId = "update",
label = "UPDATE NOW"
),
id = "tickerBox",
closable = F,
maximizable = F,
width = 12,
height = "250px",
solidHeader = FALSE,
collapsible = F
)
)
)
}
server <- function(input, output, session){
# updateSelectizeInput(
# session = session,
# label = "Ticker:",
# inputId ="ticker",
# choices = tickers,
# server = TRUE
# )
observeEvent(input$ticker, {
choices <- tickers[startsWith(tickers$symbol, input$ticker), ]
updateSelectizeInput(
session = session,
label = "Ticker:",
inputId ="ticker",
choices = choices,
server = TRUE
)
})
}
shiny::shinyApp(ui = ui, server = server)
# REPREX for selectize
library(shiny)
tickers <- rep(rownames(mtcars), 850)
ui <- {
renderUI(
shiny::fluidRow(
bs4Dash::box(
title = shiny::selectizeInput(
inputId = "ticker",
label = "Ticker:",
choices = NULL,
selected = "AAPL",
options = list(
placeholder = "e.g AAPL",
create = TRUE,
maxOptions = 50L
)
),
actionButton(
inputId = "update",
label = "UPDATE NOW"
),
id = "tickerBox",
closable = F,
maximizable = F,
width = 12,
height = "250px",
solidHeader = FALSE,
collapsible = F
)
)
)
}
server <- function(input, output, session){
# One call to try and load ticker df
observeEvent(input$update, {
updateSelectizeInput(
session = session,
label = "Ticker:",
inputId ="ticker",
choices = ticker,
server = TRUE
)
})
}
shiny::shinyApp(ui = ui, server = server)
SEE SIMILAR POSTS:
SO POST 1, SO POST 2, SO POST 3
What do you think about something like this?
library(shiny)
tickers <- rep(rownames(mtcars), 850)
ui <- fluidPage(
tags$head(
tags$script(
HTML(
'document.addEventListener("keydown", function(e) {
Shiny.setInputValue("key_pressed", e.key);
})'
)
)
),
fluidRow(
column(2, selectizeInput("select", "Select", choices = "")),
column(1, actionButton("btn", "Search"))
)
)
server <- function(input, output, session) {
observeEvent(input$btn, {
req(input$key_pressed)
updateSelectizeInput(session, "select", choices = tickers[startsWith(tickers, input$key_pressed)], server = TRUE)
})
}
shinyApp(ui, server)
Basically I think it is not possible to just use the words which are putted to the selectInput and we need separate input. I think that selectInput is truthy (isTruthy()) only after some option was chosen (and it can't be "" of course), so we can't use anything which is putted as a word to the selectInput box before some option is actually chosen. I'm not sure, but if I'm right, it is necessary to have separate input for what you want.
However, if we could assume that:
User will use only one letter to get the options to choose
Then we can use "keydown" event (keydown). Now the user doesn't need to put anything to the selectInput box, she/he can just use a key in the keyboards, like C (letter size does matter here, because we are using startsWith()) and then push "Search" button (but of course this letter can still be put to the selectInput box to mimic what you tried to achieve). We could even imagine solution without the button, but I'm afraid in most use-cases it will be not recommended, I mean if user can interact with the app using keyboard not only to choose the options, but also for other purposes, then we would recompute new options everytime user uses key in the keyboard for - well - nothing.
Turns out that selectizeInput doesn't accept a df and must be an atomic vector. When I used tickers[[1]], the issue seemed to be solved, and the list would no longer flash.

Why selectizeInput does not select the first choices when server = FALSE?

The documentation of selectizeInput describes the argument selected as follows.
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.
I interpreted this sentence as the selected argument would be the first element of the choices argument if nothing is specified for the selected. However, in the following example, after the selection of any numbers for the first selectizeInput, the second selectizeInput does not select the first choice. It still displays the default message as a placeholder.
Notice that if I set server = TRUE, the second selectizeInput would be able to display the first choice as the selected.
I am wondering why server = TRUE or server = FALSE affects if the selected can be the first element in choices. I also want to know how I can make the behavior of server = FALSE as the same as when server = TRUE.
library(shiny)
ui <- fluidPage(
headerPanel("shinyStore Example"),
sidebarLayout(
sidebarPanel = sidebarPanel(
selectizeInput(inputId = "Select1", label = "Select A Number",
choices = as.character(1:3),
options = list(
placeholder = 'Please select a number',
onInitialize = I('function() { this.setValue(""); }'),
create = TRUE
))
),
mainPanel = mainPanel(
fluidRow(
selectizeInput(inputId = "Select2",
label = "Select A Letter",
choices = character(0),
options = list(
placeholder = 'Please select a number in the sidebar first',
onInitialize = I('function() { this.setValue(""); }'),
create = TRUE
))
)
)
)
)
server <- function(input, output, session) {
dat <- data.frame(
Number = as.character(rep(1:3, each = 3)),
Letter = letters[1:9]
)
observeEvent(input$Select1, {
updateSelectizeInput(session, inputId = "Select2",
choices = dat$Letter[dat$Number %in% input$Select1],
server = FALSE)
})
}
shinyApp(ui, server)
Why not create the second selectizeInput completely on the server side?
library(shiny)
ui <- fluidPage(
headerPanel("shinyStore Example"),
sidebarLayout(
sidebarPanel = sidebarPanel(
selectizeInput(inputId = "Select1", label = "Select A Number",
choices = as.character(1:3),
options = list(
placeholder = 'Please select a number',
onInitialize = I('function() { this.setValue(""); }'),
create = TRUE
))
),
mainPanel = mainPanel(
fluidRow(
uiOutput('select2')
)
)
)
)
server <- function(input, output, session) {
dat <- data.frame(
Number = as.character(rep(1:3, each = 3)),
Letter = letters[1:9]
)
output$select2 <- renderUI({
req(input$Select1)
selectizeInput(inputId = "Select2",
label = "Select A Letter",
choices = dat$Letter[dat$Number %in% input$Select1])
})
}
shinyApp(ui, server)

Dynamically adding a user interface with multiple inputs

I am trying to dynamically add an input to a Shiny page. I want the user to select from a dropdown a choice and then have the option to add a numeric input corresponding to that choice.
Once I run the app I have two fields "Choice" and "Number". I want the user to click the "Add UI" button and be presented with another "Choice 2" and a "Number 2", when they click again they get "Choice 3" and "Number 3" etc.
Currently all I can manage to add is just another dropdown box. When I try to add numericInput(inputId = "numericWhichGoesWithIndicatorChoice", label = "Number", value = 3) to the insertUI part of the code I get errors.
Additionally, I would like to make it dynamic in the sense that the user can add as many inputs as they want and the inputs will be stored. i.e, inputId = "indicatorChoice", inputId = "indicatorChoice2", inputId = "indicatorChoice3" etc.
Code:
library(shiny)
ui <- fluidPage(
actionButton("add", "Add UI"),
wellPanel(
selectInput(inputId = "indicatorChoice", label = "Choice", choices = c("choice1", "choice2", "choice3")),
numericInput(inputId = "numericWhichGoesWithIndicatorChoice", label = "Number", value = 3)
)
)
server <- function(input, output, session) {
observeEvent(input$add, {
insertUI(
selector = "#add",
where = "afterEnd",
ui = selectInput(inputId = "indicatorChoice", label = "Choice 2", choices = c("choice1", "choice2", "choice3"))
)
})
}
shinyApp(ui, server)

shinyfiles and renderUI don't work properly

I'm trying to use the shinyFiles library in my shinyApp, in order to give the user the possibility to select a group of files or a directory.
My idea is to use a uiOutput that changes depending on a checkbox selection.
Here I report the code, that maybe is more explicative than words
UtilityUI <- fluidPage(
titlePanel("page1"),
fluidRow(
column(2,
wellPanel(
tags$p("Check the box below if you want to choose an entire directory"),
checkboxInput(inputId = 'directory_flag', label = 'Directory path?', value = FALSE),
uiOutput("input_selection_ui")
)
),
column(8
#...
)
)
)
UtilityServer <- function(input, output, session) {
output$input_selection_ui <- renderUI({
if(input$directory_flag == TRUE) {
shinyDirButton(id = "infiles", label = "Choose directory", title = "Choose a directory")
} else {
shinyFilesButton(id = "infiles", label = "Choose file(s)", title = "Choose one or more files", multiple = TRUE)
}
})
shinyFileChoose(input, 'infiles', roots=getVolumes(), session=session, restrictions=system.file(package='base'))
shinyDirChoose(input, 'infiles', roots=getVolumes(), session=session, restrictions=system.file(package='base'))
}
shinyApp(UtilityUI, UtilityServer)
The problem borns when the "shinyFiles" button is pressed: the popup window doesn't load the roots, in both cases (shinyDirButton and shinyFilesButton).
If I don't use the uiOutput function everything works well... But in that case I cannot change my UI dinamically...
Thanks a lot for your replies,
Inzirio
It seems I can't get it to work either with renderUI(). Instead I implemented the same behavior using conditionalPanel() to show alternative buttons. This seems to work. Here is the code:
ui <- shinyUI(fluidPage(
checkboxInput(
inputId = 'directory_flag',
label = 'Directory path?',
value = FALSE
),
conditionalPanel(
"input.directory_flag == 0",
shinyFilesButton(
id = "infile",
label = "Choose file(s)",
title = "Choose one or more files",
multiple = TRUE
)
),
conditionalPanel(
"input.directory_flag == 1",
shinyDirButton(id = "indir", label = "Choose directory", title = "Choose a directory")
)
))
server <- shinyServer(function(input, output, session) {
shinyFileChoose(
input,
'infile',
roots = getVolumes(),
session = session,
restrictions = system.file(package = 'base')
)
shinyDirChoose(
input,
'indir',
roots = getVolumes(),
session = session,
restrictions = system.file(package = 'base')
)
})
shinyApp(ui, server)

change data for next input dynamically

i have two select input in my
UI.R
library(shiny)
ContextElements = c("choice1", "choice2", "choice3")
shinyUI(pageWithSidebar(
headerPanel(""),
sidebarPanel(
h4("test for selectize input"),
selectizeInput(inputId = "firstAxe", label = h4("First Axe"),
choices=ContextElements, selected = NULL, multiple = FALSE,
options = NULL),
hr(),
selectizeInput(inputId = "twoAxe", label = h4("Second Axe"),
choices=NULL, selected = NULL, multiple = FALSE,
options = NULL)
),
mainPanel(
)
))
i want that the next selectizeinput choices ("twoAxe") to be filled dynamically with the remained choices drom the first one, that's mean if i choosed the first choice if the first one, the second choices will be choice2 and choice3
Thanks
You can do this in server.r using updateSelectizeInput . Lets assume that ContextElements is available to the server - either defined in global.r or in both server.r and ui.r. Then this should work:
observe({
input$firstAxe # makes the second selectize change when the first one does
updateSelectizeInput({session, inputId="twoAxe",
choices=as.list( ContextElements[!ContextElements %in% input$firstAxe] ) })
})
As you change you choice in firstAxe you should see the choices in twoAxe respond.

Resources