1

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 uiOutputs, other inputs, including selectInputs 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)
tamarack
  • 377
  • 1
  • 11
  • 3
    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](https://shiny.rstudio.com/articles/modules.html) where you can "namespace" elements so you don't have conflicting IDs. But in this case, I'm not sure why each game is getting it's own renderUI. It seems you just want one value for Age since all the code in each group is the same. – MrFlick Sep 21 '21 at 18:12
  • @MrFlick thank you! As I explained in the question, each game is getting its own form because the paper form that is being used for data entry is different for each animal (different order and not all the same fields are present), and it needs to be as streamlined a form as possible because it will be used hundreds of times each year by many different technicians, so anything that isn't very clear can cause big problems. I'm not sure how to mark your comment as the correct answer, so I'm pasting it into the answer box and marking it as the answer, hopefully that's correct etiquette. – tamarack Sep 21 '21 at 18:35

1 Answers1

2

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.

tamarack
  • 377
  • 1
  • 11