multiple choice box in R/shiny - adding a scroll bar - r

I build an R/shiny web app. I want to have a multiple choice box (I use checkboxGroupInput(), but am open to alternatives). However, the list of choices is long and I want to contain it in a relatively small box of options (that shows 5-6 options at a time) with a scroll bar that enables to scroll through the entire list of choices.
Is there a way this can be done?
minimal example:
ui.R
library(shiny)
choices = paste("A",1:30,sep="_")
shinyUI(pageWithSidebar(
# Application title
headerPanel("my title"),
sidebarPanel(
checkboxGroupInput("inp", "choose any of the following", choices)
),
mainPanel(
tableOutput("result")
)
))
server.R
library(shiny)
shinyServer(function(input, output) {
myInput <- reactive({
input$inp
})
output$result <- renderTable({
x = myInput()
if(length(x)==0) {
x = "No Choice Made"
}
matrix(x,ncol=1)
})
})

I found that using selectInput(..., multiple = TRUE) does the trick.

Related

One reactive function to be displayed on two different pages interactively

I have an application which has 3 tabItems. I want to use a slider on second page to display same result on 3rd page interactively, i.e. if 2nd page slider changes then 3rd page slider should also change respectively.
I have a reactive function on server side
choose_segment <- reactive({
Multiple conditions for dropdown{Due to security cant share the exact code.}
})
and this choose_segment is refered in UI once and now i want to use it on the third page as well, but when i am calling the function on third page it is not displaying any thing on ui and also not giving any error.
in UI it is called inside UIoutput.
uiOutput(choose_segment())
My observations : I think as per my study we can not call one function directly twice, so what i am doing is i have made two different functions and calling same function from them, i.e.
output$chooseSegment1 <- renderUI({
choose_segment()
})
output$chooseSegment2 <- renderUI({
choose_segment()
})
Issue : it is giving me output but they both are not interactive :(
Kindly provide a solution so that i can make both the sliders work in interactive manner.
I have faced the same scenario, in that i was suppose to change the code structure.
I made dynamic output uiOutput to the Dropdown menu ob ui and then used the same in my server as Input$xyz in observe on server and it worked for me.
Code :
UI : column(3, selectInput(inputId="ABC",label= "Choose ABC"))
column(3, selectInput(inputId="ABC1",label= "Choose ABC"))
Server : observe({
if(is.null(tab2_summary())) return(NULL)
updateSelectInput(session, "ABC", value = input$ABC)
})
observe({
updateSelectInput(session, "ABC1", value = input$ABC)
})
observe({
updateSelectInput(session, "ABC", value = input$ABC1)
})
So this is how i was able to make the selectInput interactive on two different page.
For your reference there is one full reproducible code.
Kindly refer,
library(shiny)
# UI ----------------------------------------------------------
ui <- navbarPage("Navbar!",
tabPanel("Plot", sidebarLayout(sidebarPanel(
radioButtons("yaxis1", "y-axis", c("speed"="speed", "dist"="dist"),
selected = "speed"
)),
mainPanel( plotOutput("plot"),
textOutput("test2")))), # for input checking
tabPanel("Summary", sidebarLayout(sidebarPanel(
radioButtons("yaxis2", "grouping-var", c("speed"="speed", "dist"="dist")
)),
mainPanel(
verbatimTextOutput("summary"),
textOutput("test1")
)))
)
# Server ------------------------------------------
server <- function(input, output, session) {
observe({
x <- input$yaxis1
updateRadioButtons(session, "yaxis2", selected = x)
})
observe({
y <- input$yaxis2
updateRadioButtons(session, "yaxis1", selected = y)
})
# output$test1 <- renderPrint({cat("yaxis1", input$yaxis1)})
# output$test2 <- renderPrint({cat("yaxis2", input$yaxis2)})
# output$plot <- renderPlot({ plot(cars[['speed']], cars[[input$yaxis1]]) })
# output$summary <- renderPrint({ summary(cars[[input$yaxis2]]) })
}
shinyApp(ui, server)
I Hope it will of your help.

dynamic number of ggplots in shiny app

I need your help, because I don't know how to solve my problem. I have my shiny app where I have data frame (imported from file) and checkboxgroupinput where I can mark which columns are for me interesting. After that in other tabpanel I would like to get two plot for each column (in one facet_wrap). All facet_wrap one under the other. The problem is that number of interesting columns is not constant. It is easy for my if I could hardcode number of rows with plots, but where it can change dynamically I have no idea how to program it, any tips from your side?
We can't solve your question without a reproducible example but you should be able to figure it out from this quick example of using uiOutput along with renderUI. This allows the use of dynamic values in UI elements.
Normally you would define your static input as checkboxGroupInput("columns", "Select the variables to plot", choices = vector_of_known_values).
However as per your question, this doesn't work if the dataset is not known beforehand (e.g.: user file upload). In this case use uiOutput in the UI part: uiOutput("ui"), so that you delay evaluation to server side. In server side you can dynamically set the choices regardless of the data structure.
output$ui <- renderUI( {
checkboxGroupInput("columns", "Select the variables to plot", choices = colnames(rv$data))
})
See full example:
library(shiny)
library(DT)
library(dplyr)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
selectInput("datasets", "Select a dataset", choices = c("mtcars", "iris"), selected = "mtcars"),
uiOutput("ui")
),
mainPanel(
DT::dataTableOutput("table")
)
)
)
server <- function(input, output, session) {
rv <- reactiveValues(data = NULL)
observe( {
rv$data <- eval(parse(text = input$datasets))
})
filtered <- reactive( {
req(input$columns)
if( all(!input$columns %in% colnames(rv$data))) {
NULL
} else {
rv$data %>% select(input$columns)
}
})
output$ui <- renderUI( {
checkboxGroupInput("columns", "Select the variables to plot", choices = colnames(rv$data))
})
output$table <- DT::renderDataTable( {
req(filtered())
DT::datatable(filtered())
})
}
shinyApp(ui, server)

Displaying selectInput in sidebar based on tabsetPanel selection in R shiny

I'm trying to generate a list in a selectInput, dynamically. I have a sidebarPanel in which I have declared a tabsetPanel. Each tabsetPanel will have different outputs, all of which I want to display in the sidebar. So the output of the first tab would be a selectInput or perhaps 2 selectInputs, while the same would go for the second tab.
Here is my sidebarPanel code in ui.R
## ui.R
sidebarPanel(
tabsetPanel(
tabPanel("aZ", uiOutput("aToZPlayerList")),
tabPanel("byTeam", uiOutput("byTeamPlayerList"))
),
),.......
In server.R, I have written the following:
## server.R
output$aToZPlayerList <- renderUI({
selectInput("alphabet", "Players A-Z", choices=aToZ, selected=0)
htmlOutput("List")
})
output$byTeamPlayerList <- renderUI({
selectInput("team", "Teams", choices=teamList, selected=0)
htmlOutput("List")
})
But this does not work, as nothing is rendered in the sidebarPanel. I feel like I'm missing something, but as I'm quite new to this, I still haven't figured it out.
I haven't been able to find an answer on here or elsewhere as of yet. Any help please? Thanks.
You should not have two widgets under one uiOutput, i would recommend to separate it:
## ui.R
sidebarPanel(
tabsetPanel(
tabPanel("aZ", uiOutput("aToZPlayerList"), htmlOutput("List")),...
## server.R
output$aToZPlayerList <- renderUI({
selectInput("alphabet", "Players A-Z", choices=aToZ, selected=0)
})...
and it will work.
[FULL EXAMPLE]
library(shiny)
fruits <- c("banana","raccoon","duck","grapefruit")
ui <- pageWithSidebar(
# Application title
headerPanel("Hello Shiny!"),
# Sidebar with a slider input
sidebarPanel(
tabsetPanel(
tabPanel("aZ", uiOutput("aToZPlayerList"), htmlOutput("List")),
tabPanel("byTeam", uiOutput("byTeamPlayerList"))
)),
# Show a plot of the generated distribution
mainPanel()
)
server <- function(input,output){
output$aToZPlayerList <- renderUI({
selectInput("alphabet", "Players A-Z", choices=c("A","B","C"), selected="A")
})
output$List <- renderUI({
HTML(paste(fruits))
})
output$byTeamPlayerList <- renderUI({
selectInput("team", "Teams", choices=c("A","B","C"), selected="B")})
}
runApp(list(ui=ui,server=server))

How to validate user input in shiny

I'm working on a very simple Shiny app that takes in a DNA codon and returns the corresponding amino acid. My issue is that I want to validate the user input so that it can only accept 3 letter (a single codon), must be capital letters, and only accept the DNA bases ( A, C, T, or G). I've had a look at Shiny's validation article, but keep on running into errors.
Here is the code I have so far:
ui.R
library(shiny)
library(shinythemes)
shinyUI(fluidPage(
theme = shinytheme("slate"),
# Application title
titlePanel("Codon lookup"),
#
sidebarLayout(
sidebarPanel(
textInput(
inputId = "codon",
label = "Enter a codon",
value = ""),
actionButton(inputId = "go", label = "Search")
),
#
mainPanel(
verbatimTextOutput("aminoacid")
)
)
))
server.R
library(shiny)
library(Biostrings)
shinyServer(function(input, output) {
data <- eventReactive(input$go, {
#validate somehow
input$codon
})
output$aminoacid <- renderText({
GENETIC_CODE[[as.character(data())]]
})
})
Also, if anyone know of an easy way to retrieve the amino acid's full name, rather than just the single letter notation, that would be helpful. Any other suggestions are welcomed.
That reactive is not really the right place to do the validation in this case since you are not using GENETIC_CODE there. So I moved it into the renderText output node. If you had a reactive doing the lookup you could do it there.
I looked at GENETIC_CODE, and it seems to make more sense to do this as a dropdown anyway and use that as validation. So I went ahead and put a selectInput in there using renderUI, as you have more flexibility if you create the input control in the server usually.
I also moved the Search button to above the codon select control as it was getting covered up by the selection.
library(shiny)
library(shinythemes)
u <- shinyUI(fluidPage(
theme = shinytheme("slate"),
# Application title
titlePanel("Codon lookup"),
#
sidebarLayout(
sidebarPanel(
actionButton(inputId = "go", label = "Search"),
uiOutput("codonselection")
),
#
mainPanel(
verbatimTextOutput("aminoacid")
)
)
))
library(Biostrings)
s <- shinyServer(function(input, output) {
data <- eventReactive(input$go, {
input$codon
})
output$codonselection <- renderUI({
choices <- names(GENETIC_CODE)
default <- "TTC"
selectInput("codon",label="Select Codon",choices=choices,selected=default)
})
output$aminoacid <- renderText({
lookupcodon <-as.character(data())
if (lookupcodon %in% names(GENETIC_CODE)){
return(GENETIC_CODE[[ lookupcodon ]])
} else {
return("Name not in GENETIC_CODE")
}
})
})
shinyApp(u,s)
Screen shot of it working:

change selectizeInput choices - wrong values in menu

I try to make a selection menu like this:
Interactively change the selectInput choices
And everything works well with the exception of one thing:
Instead to get the values (like McDonald), I get the indices although I did nothing different (see picture link below). Where could be my mistake?
Picture
Here my global.R:
partners<- read.csv("genes.csv", header=TRUE, fill=TRUE)
server.R
shinyServer(function(input, output) {
#subTable
searchResult<- reactive({
subset(partners, grepl(input$nameSearch, partners$name))
})
output$searchResults <- renderTable({
searchResult()[,1]
})
output$selectUI <- renderUI({
selectizeInput("partnerName", "Click in and select", choices=searchResult()[,1], multiple=TRUE )
})
})
ui.R
library(shiny)
shinyUI(pageWithSidebar(
# Give the page a title
titlePanel("Tilte"),
sidebarPanel(
textInput("nameSearch", "Search for name", "Blah"),
htmlOutput("selectUI"),
br(),
submitButton("Update View"),
br()
),
# Create a spot for the barplot
mainPanel(
textOutput("text"),
plotOutput("plot")
)
)
)
I think you are not getting indices, but rather the integer representation of a factor. Check the class of partners[,1]. Try
output$selectUI <- renderUI({
selectizeInput("partnerName", "Click in and select",
choices=as.character(searchResult()[,1]), multiple=TRUE )
})
You could possibly add the stringsAsFactors=FALSE option when you read the data as well.

Resources