5

in the R shiny script below, I am trying to make the functionality such that in the first submenuItem, every selectInput values depend upon the item selection in the previous column. Data is attached and the code is also written. However I am not able to achieve the desired result. Kindly run the code and check, I want the entire server logic to come under one function only. Thanks and please help.

library(shiny)
library(shinydashboard)
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(
sidebarMenu(

  id = "tabs",
  menuItem("Charts", icon = icon("bar-chart-o"),
           menuSubItem("Sub-item 1", tabName = "subitem1"),
           menuSubItem("Sub-item 2", tabName = "subitem2")
  ))),
dashboardBody(
tabItems(tabItem("subitem1", uiOutput("brand_selector")),
         tabItem("subitem2", 4))
))
server <- shinyServer(function(input, output) {
candyData <- read.table(
text = "
Brand       Candy           value
Nestle      100Grand        Choc1
Netle       Butterfinger    Choc2
Nestle      Crunch          Choc2
Hershey's   KitKat          Choc4
Hershey's   Reeses          Choc3
Hershey's   Mounds          Choc2
Mars        Snickers        Choc5
Nestle      100Grand        Choc3
Nestle      Crunch          Choc4
Hershey's   KitKat          Choc5
Hershey's   Reeses          Choc2
Hershey's   Mounds          Choc1
Mars        Twix            Choc3
Mars        Vaid            Choc2",
header = TRUE,
stringsAsFactors = FALSE)
output$brand_selector <- renderUI({
box(title = "Data", status = "primary", solidHeader = T, width = 12,
    fluidPage(
      fluidRow(
        Brand_Select <- unique(candyData$Brand),
        column(2,offset = 0, style='padding:1px;', 
selectInput("Select1","select1",Brand_Select)),
        Candy_Select <- candyData$Candy[candyData$Brand == input$Select1],
        Candy_Select <- unique(Candy_Select),
        column(2,offset = 0, style='padding:1px;', 
selectInput("Select2","select2",Candy_Select)),
        Value_Select <- candyData$value[candyData$Candy == input$Select2],
column(2, offset = 0, 
style='padding:1px;',selectInput("select3","select3",Value_Select ))
)))
})
})
shinyApp(ui = ui, server = server)

Capture

Florian
  • 24,425
  • 4
  • 49
  • 80
Adam Shaw
  • 519
  • 9
  • 24

1 Answers1

7

Your code does not work because every time one of the inputs changes, the entire renderUI runs again, thereby resetting all your inputs since they are all created from scratch again!

So how can we work around this? You could try something like the following. Note that I stripped a lot of the unnecessary formatting so it is a bit easier to see how this works.

We create the inputs in the UI, and add some observeEvents that listen to changes in the first or second input. If the first input changes, this fires the first observeEvent and will change the choices of input$Select2. Subsequently, this will trigger the second observeEvent, thereby limiting the choices in input$Select3.

I hope this helps!

library(shiny)
library(shinydashboard)

candyData <- read.table(
  text = "
    Brand       Candy           value
    Nestle      100Grand        Choc1
    Netle       Butterfinger    Choc2
    Nestle      Crunch          Choc2
    Hershey's   KitKat          Choc4
    Hershey's   Reeses          Choc3
    Hershey's   Mounds          Choc2
    Mars        Snickers        Choc5
    Nestle      100Grand        Choc3
    Nestle      Crunch          Choc4
    Hershey's   KitKat          Choc5
    Hershey's   Reeses          Choc2
    Hershey's   Mounds          Choc1
    Mars        Twix            Choc3
    Mars        Vaid            Choc2",
  header = TRUE,
  stringsAsFactors = FALSE)

ui <- fluidPage(
  selectInput("Select1","select1",unique(candyData$Brand)),
  selectInput("Select2","select2",choices = NULL),
  selectInput("Select3","select3",choices=NULL ))

server <- function(input, output,session) {
 observeEvent(input$Select1,{
   updateSelectInput(session,'Select2',
           choices=unique(candyData$Candy[candyData$Brand==input$Select1]))
 }) 
  observeEvent(input$Select2,{
    updateSelectInput(session,'Select3',
           choices=unique(candyData$value[candyData$Brand==input$Select1 & candyData$Candy==input$Select2]))
  }) 

}

shinyApp(ui = ui, server = server)
Florian
  • 24,425
  • 4
  • 49
  • 80
  • Hi the solution is fine, but I kindly request you to fit this in the UI as I have to follow the UI originally, I am finding difficult to put your content in my UI, kindly update the code. – Adam Shaw Jan 22 '18 at 07:50
  • Thanks for the help, I have figured this out. – Adam Shaw Jan 22 '18 at 08:10
  • Great, nice that you were able to solve that last part yourself. – Florian Jan 22 '18 at 08:41
  • I have one more issue with my script above, I am not able to use uiOutput at multiple places, e.g. in my script if you see 13th and 14th line, if I use uiOutput at two places, I am not able to see the result, can you suggest a fix here which does not slow my script down? Thanks. – Adam Shaw Jan 22 '18 at 10:19
  • Actually I am using this solution on 16+ menuitems, don't want the script to slow down. – Adam Shaw Jan 22 '18 at 10:20
  • Hi Adam, could you maybe add that as a new question on StackOverflow? And add there the code that you are currently trying to run? – Florian Jan 22 '18 at 11:38
  • https://stackoverflow.com/questions/48380426/using-shiny-plotoutput-in-multiple-places-in-r, Done – Adam Shaw Jan 22 '18 at 11:39
  • I guess using shiny modules can help, but not sure how to integrate "observeEvent" with that. – Adam Shaw Jan 22 '18 at 11:40
  • Sir, if I can suggest you here, I need to use your solution in the template above with around 16 menuItems. That can be achieved using Shiny Modules, however I don't know how to use observeEvent there as "input$" can only be used inside the server, kindly help. – Adam Shaw Jan 22 '18 at 12:39
  • 1
    Hi @AdamShaw, as mentioned above; please consider asking your question as a new one on Stack overflow, maybe the following guidelines can help you: https://stackoverflow.com/questions/48343080/how-to-create-a-good-shiny-reproducible-example – Florian Jan 22 '18 at 13:05
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/163657/discussion-between-adam-shaw-and-florian). – Adam Shaw Jan 22 '18 at 15:02
  • I have used your code and worked myself on the my own UI, just that the result needs to put in multiple places, Please help me with this new post https://stackoverflow.com/questions/48394545/usage-of-uioutput-in-multiple-menuitems-in-r-shiny-dashboard – Adam Shaw Jan 23 '18 at 05:03
  • Hi Adam, I am afraid I have no experience in Shiny modules. – Florian Jan 23 '18 at 05:57
  • thanks for the help here, however I have got a lot close, see this if you can help me with a fix here, you can check the solution posted: https://stackoverflow.com/questions/48394545/usage-of-uioutput-in-multiple-menuitems-in-r-shiny-dashboard/48394758#48394758 – Adam Shaw Jan 23 '18 at 06:00
  • Friends, please, could you take a look at another question that is similiar? (https://stackoverflow.com/questions/61559805/link-selectinput-with-sliderinput-in-shiny?noredirect=1#comment108896301_61559805).. Thank you very much! –  May 02 '20 at 17:47