I'm developing a shiny app where the user will be able to describe the room occupancy of multiple houses. The main idea of the code is to input the number of houses (inputId = 'n_houses'), i.e. the number of tabs in the mainPanel is equal to the number of houses inputed. Each house tab should be connected to a different sidebarPanel, i.e. when accessing the house tab in the mainPanel, the correspondent sidebarPanel is displayed. In the sidebarPanel, the number of rooms (inputId = 'n_rooms') of the correspondent house tab is inputed. Finally, each room is inputed with an occupancy value (inputId = 'occup'), that can be either 'liv' (living room) or 'dorm' (dormitory).
Each mainPanel tab should display the occupancy of all its correspondent rooms.
A simple example of the inputs follows:
- n_houses = 2 (two houses)
- n_rooms1 = 2 (two rooms in the first house) - 2.a. occup11 = 'liv' (living room); 2.b. occup12 = 'dorm' (dormitory)
- n_rooms2 = 3 (three rooms in the second house) - 3.a. occup21 = 'dorm' (dormitory); 3.b. occup22 = 'liv' (living room); 3.c. occup23 = 'dorm' (dormitory) Ps.: it sums a total of 5 room occupancies.
Then, the outputs should be:
- mainPanel tab 1 (house 1): 'Results for house 1: liv dorm dorm'
- mainPanel tab 2 (house 2): 'Results for house 2: liv dorm'
The code chunk below shows my last efforts to solve this issue.
# shiny user interface
ui = shinyUI(
  fluidPage(
    headerPanel(
      h1('ROOMS OCCUPANCY', align = 'center')
    ),
    sidebarPanel(
      sliderInput(
        inputId = 'n_rooms',
        label = 'Choose the number of rooms in the correspondet house:',
        min = 2, max = 5, step = 1, value = 3
      ),
      uiOutput('rooms')
    ),
    mainPanel(
      sliderInput(
        inputId = 'n_houses', 
        label = 'Choose the number of houses:',
        min = 1, max = 20, step = 1, value = 1
      ),
      uiOutput('houses')
    )
  )
)
# auxiliar functions to shiny server
# generate room tab panel
GenRoomTab = function(ind_room, ind_house) {
  panel = tabPanel(
    title = paste('Room', ind_room),
    value = paste0(ind_house, ind_room),
    radioButtons(
      inputId = paste0('occup', ind_house, ind_room),
      label = 'Room occupancy:',
      choices = list('Living room' = paste0('liv', ind_house, ind_room),
                     'Dormitory' = paste0('dorm', ind_house, ind_room)),
      selected = paste0('liv', ind_house, ind_room)
    )
  )
  return(panel)
}
# generate room tabset panel
GenRoomTabset = function(ind_house, n_rooms) {
  tab_panels = lapply(1:n_rooms, GenRoomTab, ind_house)
  tabset_panel = do.call(tabsetPanel, tab_panels)
  condition_panel = list(condition = paste('input.tabselected ==', ind_house), tabset_panel)
  return(condition_panel)
}
# generate house tab panel
GenHouseTab = function(ind_house) {
  panel = tabPanel(
    title = paste('House', ind_house),
    value = ind_house,
    h4(paste('Results for house', ind_house, ':'))
  )
  return(panel)
}
# generate summary tab panel
GenSummTab = function() {
  panel = tabPanel(
    title = 'Summary'
  )
  return(list(panel))
}
# shiny server
server = shinyServer(
  function(input, output) {
    # define room tabset panels
    output$rooms = renderUI({
      room_tabsets = do.call(GenRoomTabset, list(1:input$n_houses, input$n_rooms))
      do.call(conditionalPanel, room_tabsets)
    })
    # define house tab panels
    output$houses = renderUI({
      house_tab_panels = lapply(1:input$n_houses, GenHouseTab)
      summ_tab_panel = GenSummTab()
      tab_panels = c(list(type = 'tab', id = 'tabselected'),
                     house_tab_panels, summ_tab_panel)
      do.call(tabsetPanel, tab_panels)
    })
  }
)
# associate ui to server
shinyApp(ui = ui, server = server)
When I run this code the following warning message shows up:
Warning: Error in radioButtons: The 'selected' argument must be of length 1 105: stop 104: radioButtons 100: FUN [/home/rodox/git/giz/app/app.r#29] 99: lapply 98: [/home/rodox/git/giz/app/app.r#44] 96: renderUI [/home/rodox/git/giz/app/app.r#71] 95: func 82: origRenderFunc 81: output$rooms 1: runApp
I think it is related to selected = paste0('liv', ind_house, ind_room), inside function GenRoomTab(). The GenRoomTab() is applied within lapply(1:n_rooms, GenRoomTab, ind_house), inside the function GenRoomTabset(). However it seems strange to me, since ind_house is a vector as well as ind_room.
Another difficulty that I have is to display the occupancy of all the rooms into the correspondent house tab.
I've been trying to solve this for a while, but couldn't solve it... I hope someone can save me!