I am writing an app that will be used to enter data from paper forms into an SQL database. The data are from wildlife capture records, and will go into a single table, so the different forms share a lot of the same fields (e.g. weight, age, species, etc), but some of the forms have different fields, or the same fields in a different order. I don't want to have unused fields visible, and I want the Shiny app to match the field order on the data sheet so the user can just tab through. So, I have a uiOutput
for each species that renders based on the species initially selected from a menu. Then, within those uiOutput
s, other inputs, including selectInput
s where the choices are dependent on the species selected.
Since many of the fields are the same, I want to just have one dataframe at the end that uses all the inputs, regardless of what the selected species is, rather than a bear dataframe, an elk dataframe, etc. So, input$Age
will be rendered multiple times rather than input$bearAge
, input$elkAge
each rendered once. Then, eventually, I would have a dataframe that is entrydata <- data.frame(Age = input$Age)
, rather than bearentrydata <- data.frame(Age = input$bearAge)
, elkentrydata <- data.frame(Age = input$elkAge)
, etc.
The problem is that shiny seems to really not like having the same input value used over and over again, and it will randomly stop recognizing new input$Age
for species 1, then start recognizing it again for species 2, then work again for species 1. I put a print statement inside observeEvent(input$Age, {})
to test. I've tried to fix it with choices = someAgeVector
, where someAgeVector
updates inside an observeEvent(input$GameID,{})
and the same thing happens, leading me to believe it is a problem with reusing the same inputId.
Is there a way to have the same input rendered multiple times?
Here is a simplified version of the app:
library(shiny)
game <- c('', 'Black_Bear', 'Elk', 'Mule_Deer')
## age class data frame
ages <- read.table(header = T, text = "
Age_Class Game
Cub Black_Bear
Yearling Black_Bear
Subadult Black_Bear
Adult Black_Bear
6mo Elk
Yearling Elk
2-9yr_old Elk
10-14yr_old Elk
>15yr_old Elk
Neonate Mule_Deer
Fawn Mule_Deer
Yearling Mule_Deer
Adult Mule_Deer
Unknown Mule_Deer
")
ui <- fluidPage(
selectInput(inputId = 'GameID', label = 'Game', choices = game),
uiOutput(outputId = 'bearUI'),
uiOutput(outputId = 'elkUI'),
uiOutput(outputId = 'deerUI'),
)
server <- function(input, output, session) {
observeEvent(input$Age, {
print(input$Age)
})
output$bearUI <- renderUI({
req(input$GameID == 'Black_Bear')
selectInput(inputId = 'Age', label = 'Age', choices = c(ages[ages$Game == input$GameID,]$Age_Class))
})
output$elkUI <- renderUI({
req(input$GameID == 'Elk')
selectInput(inputId = 'Age', label = 'Age', choices = c(ages[ages$Game == input$GameID,]$Age_Class))
})
output$deerUI <- renderUI({
req(input$GameID == 'Mule_Deer')
selectInput(inputId = 'Age', label = 'Age', choices = c(ages[ages$Game == input$GameID,]$Age_Class))
})
}
shinyApp(ui = ui, server = server)
Per @MrFlick : ID's must be unique on the page. This is because they are implemented as actually HTML id attributes on the nodes. Web browsers do not do well with duplicate IDs. For a better strategy, try something like shiny modules where you can "namespace" elements so you don't have conflicting IDs.