1

I am struggling to use a reactive environment in a tabPanel environment in Shiny.

I want to use a reactive data file in a tabPanel environment in a inputPanel in Shiny. Here follows the code (I generate the data to use in C:/Temp below):

Data:

dir.create(file.path("C:","Temp"), showWarnings = FALSE)
write.csv(rbind("A","B","C","D"), "C:/Temp/A.csv",row.names = FALSE)
write.csv(rbind("A","B","C","D"), "C:/Temp/B.csv",row.names = FALSE)
write.csv(rbind("A","B","C","D"), "C:/Temp/C.csv",row.names = FALSE)

Shiny:

---
title: "Reactive in Tab environment"
output: html_document
runtime: shiny
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```

```{r , echo=FALSE}
    navbarPage("Analysis",
    tabPanel("File Choice",
      inputPanel(
      selectInput("File", label = "File Choice",
                  choices = c("A","B","C"), selected = c("A","B","C")[1])
                     ),
    Data <- reactive({read.csv(paste0("C:/Temp/",input$File,".csv"))})
    ),
    tabPanel("File Show",
      inputPanel(
      selectInput("Choices", label = "Choices",
                  choices = Data()[,1], selected = Data()[,1][1])
                     )))


    ```
4
  • @slickrickulicious yes I want to embed the app in Rmarkdown as well.. Commented Dec 18, 2015 at 11:20
  • what's the actual problem? Commented Dec 18, 2015 at 11:24
  • @MLavoie as mentioned, I cannot get this example working. It seems as though the reactive call in a tabPanel environment fails. This is just one example, I've tried other iterations. Any ideas on getting this MWE to work? I.e. get two working input panels? Commented Dec 18, 2015 at 12:31
  • @slickrickulicious Doing that I still get an error. See e.g.: {r, echo = FALSE} navbarPage("Analysis", tabPanel("File Choice", inputPanel( selectInput("File", label = "File Choice", choices = c("A","B","C"), selected = c("A","B","C")[1])))) Data <- reactive({ read.csv(paste0("C:/Temp/",input$File,".csv")) }) navbarPage("Analysis2", tabPanel("File Show", inputPanel( selectInput("Choices", label = "Choices", choices = isolate(Data)[,1], selected = isolate(Data)[,1][1]) ))) Commented Dec 18, 2015 at 14:29

1 Answer 1

2

I think writing shiny apps in RMarkdown documents can be somewhat confusing since the separation between UI/server input/output isn't sharply defined.

I would take your reactive values (Data), and other things that would go in the server, and define them outside of your UI components (the navbarPage, tabPanels, etc).

I also like to write the various interface components separately, but that is just a personal preference (and you can also write them in different documents and source them in to keep the code smaller).

In the following example (very similar to yours), the three documents can be selected in one tab, then printed as a table under the other tab. Note, you will need to fix the path to go to where you have your documents (I would use file.path so you know there won't be problems on different OSes).

---
title: "Reactive in Tab environment"
runtime: shiny
output:
    html_document
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)

## For reproducibility you can run this to create a Temp directory with
## some data.frames in your current directory
if (!file.exists('Temp')) {
  dir.create('Temp')
  for (f in paste0(LETTERS[1:3], '.csv'))
    write.csv(data.frame(A=sample(letters[1:10]), B=sample(10)), file.path('Temp', f))
}
```

```{r app, echo=FALSE}

## Initialize data with something
## Replace the path in `file.path` with the path to your files
docs <- paste0(LETTERS[1:3], '.csv')                       # your documents
Data <- reactive({ 
  f <- if (is.null(input$File)) docs[[1]] else input$File  # initialize reading A.csv
  read.csv(file.path('Temp', f))
})

## UI components 
## Note: these are not reactive, so when you want to use a reactive value like Data(),
## wrap it in isolate().
## I like to separate things, but also could plug in to tabPanels
panel1 <- tagList(
  inputPanel(
    selectInput("File", label = "File Choice",
                choices = docs, selected=docs[[1]])
  )
)

panel2 <- tagList(
  sidebarLayout(
    sidebarPanel(
      selectInput("Choices", label = "Choices",
                  choices = isolate(Data()[,1]), 
                  selected = isolate(Data()[,1][[1]])
                  )
    ),
    mainPanel(
      renderTable({ Data() })
    )
  )
)

navbarPage("Analysis",
           tabPanel("File Choice", panel1),
           tabPanel("File Show", panel2))

  ```
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks that is pretty neat! I agree, much easier to keep it all apart.
I've also come across the function renderUI() which allows the use of reactive data in selectInput calls..

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.