Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use shiny conditional panel

Tags:

r

shiny

Hi currently I've got a sample data set like this

 df<- data.frame(site = c('A1', 'A1', 'A1', 'B1', 'B1','B1','B1','C1','C1'), 
                 part = c('a1', 'a1', 'a2', 'b1', 'b1', 'b2','b3','c1','c2'),
                 value = c(2,3,4,5,6,7,8,9,10))

> df
site part value
  A1   a1     2
  A1   a1     3
  A1   a2     4
  B1   b1     5
  B1   b1     6
  B1   b2     7
  B1   b3     8
  C1   c1     9
  C1   c2    10

I would like to put a side bar in shiny user interface with two select boxes. One is "choose" site and the other one is "part".

shinyUI(

fluidPage(    

titlePanel("Choose Site, part"),

sidebarLayout(      


  sidebarPanel(
    selectInput("select_site", label = "Select Site", 
                choices = unique(df$site), 
                selected = unique(df$site)[1]),

      selectInput("select_part", label = "Select Part", 
                  choices = unique(df$part), 
                  selected = unique(df$part)[1])

  ),

  mainPanel(
    plotOutput("example")  
  )

)
)
)

The objective is when I choose A1 in "select_site", I can only choose a1 or a2 in "select_part". However this code right now can choose a1, a2, b1, b2, b3, c1, c2 in "select_part" no matter how I choose in "select_site".

In the real data set there are a lot more sites and parts than this example so I'm looking for a generic way to identify the parts within each site rather than type in the names myself.

Can anyone help me with some modification of this code?

Thanks in advance

like image 536
Lambo Avatar asked Aug 15 '14 04:08

Lambo


1 Answers

You should look at updateSelectInput instead of conditionalPanel. What conditionalPanel does is to hide some UI elements completely, instead of hiding some options in a selectInput.

In your case, you can create an observer in server.R that watches for the selection made by the user for select_site.

ui.R

shinyUI(
  fluidPage(    
    titlePanel("Choose Site, part"),
    sidebarLayout(      


      sidebarPanel(
        selectInput("select_site", label = "Select Site", 
                    choices = list("A1"="A1", "B1"="B1", "C1"="C1"), 
                    selected = "A1"),

        selectInput("select_part", label = "Select Part", 
                    choices = NULL, 
                    selected = NULL) # empty for now, will be updated in server.R

      ),

      mainPanel(
        plotOutput("example")  
      )

    )
  )
)

Now create a global.R to share the df object with both ui.R and server.R.

global.R

df <- data.frame(site = c('A1', 'A1', 'A1', 'B1', 'B1','B1','B1','C1','C1'), 
                 part = c('a1', 'a1', 'a2', 'b1', 'b1', 'b2','b3','c1','c2'),
                 value = c(2,3,4,5,6,7,8,9,10))

site_choices <- as.list(df$site)
names(site_choices) <- df$site

Finally, at the server side, use an observer to update the select_part's options when the selection of select_site changes.

server.R

library(shiny)

shinyServer(function(input, output, session){
  observe({
    if (input$select_site != "") {
      part_choices <- as.list(df$part[df$site == input$select_site])
      names(part_choices) <- df$part[df$site == input$select_site]

      updateSelectInput(session, "select_part", choices=part_choices)
    }
  })
})

Final comment

You can make use of conditionalPanel, if you have other site-specific elements that you only want to display conditionally. For example, if site A1 has some very specific input controls or output elements that do not exist in other sites, you can wrap those input/output elements in a condtionalPanel with the condition parameter: condition="input.select_site == 'A1'". (Note that you use . here instead of $ because this condition is evaluated in your browser by Javascript, not in Shiny by R. )

Then, once the user switches to other sites, those elements in the conditionalPanel will disappear. (More interestingly, output elements that are hidden won't be updated even if their dependent inputs change. Because it make little sense to update something that is invisible to the user.)

like image 148
Xin Yin Avatar answered Sep 18 '22 08:09

Xin Yin