Reputation: 13
I am making a shiny dashboard that contains lots of tables that should appear and behave identically, but contain different data. In order to make my code more modular, I have written a function that will hold the shinyApp() call so that it can be reused. Here is a link to the official shiny documentation showing the use of shinyApp() within a user defined function.
The function works to an extent, because it renders a datatable, but it does not react to changes in the reactive data frame that is input.
Here is the function I have written, along with the libraries I've used and the sidebar that the datatable should be reacting to:
---
title: "Test"
runtime: shiny
output:
flexdashboard::flex_dashboard:
navbar:
orientation: rows
vertical_layout: fill
---
```{r packages, include = FALSE}
library(flexdashboard)
library(DT)
library(dplyr)
library(shiny)
library(datasets)
test_data <- datasets::CO2
data_chart <- function(shiny_data, col_names){
shinyApp(
ui = fluidPage(
DT::dataTableOutput("results")
),
server = function(input, output, session) {
output$results <- DT::renderDataTable(
datatable(
shiny_data,
filter = 'top',
colnames = col_names,
rownames = FALSE,
options = list(
dom = 'lptpi',
scrollY = '',
order = list(3, 'desc')
)
)
)
}
)
}
```
Header
===
Sidebar {.sidebar}
---
```{r}
checkboxGroupInput(
inputId = 'Plant1',
label = h4("Age Group"),
choices = list('Qn1', 'Qn2', 'Qn3', 'Qc1', 'Qc2', 'Qc3', 'Mn1', 'Mn2', 'Mn3', 'Mc1', 'Mc2', 'Mc3'),
selected = c('Qn1', 'Qn2', 'Qn3', 'Qc1', 'Qc2', 'Qc3', 'Mn1', 'Mn2', 'Mn3', 'Mc1', 'Mc2', 'Mc3')
)
```
Row
---
```{r}
data_1 = reactive({test_data %>%
filter(Plant %in% input$Plant1) %>%
data.frame()
})
data_chart(test_data, c('Plant', 'Type', 'Treatment', 'Conc', 'Uptake'))
I think the problem has something to do with the fact that within the function, I refer to the reactive data set "shiny_data()" as "shiny_data" (without parenthesis), which makes it behave statically. However, I have tried adding the parenthesis and I get the error:
ERROR: could not find function "shiny_data()"
Furthermore, I have tried wrapping various sections of the code with reactive({}) to try to explicitly define the data as reactive, but with no luck.
I'm confident this isn't an issue with having the shinyApp() within a function, because when I make a function that I have hard coded the reactive data_1() data frame, it reacts to changes in the sidebar. Here is an example of this result (the function is exactly the same as above, but instead of passing shiny_data into the function, data_1() is hardcoded in):
Row
---
```{r}
data_chart2 <- function(col_names){
shinyApp(
ui = fluidPage(
DT::dataTableOutput("results")
),
server = function(input, output, session) {
output$results <- DT::renderDataTable(
serverTable <- datatable(
data_1(),
filter = 'top',
colnames = col_names,
rownames = FALSE,
options = list(
dom = 'lptpi',
scrollY = '',
order = list(3, 'desc')
)
)
)
}
)
}
data_chart2(c('Plant', 'Type', 'Treatment', 'Conc', 'Uptake'))
```
As you can see in both provided examples, the data in the rendered datatable only reacts when the reactive dataset is explicitly called in the function. is there any way that at the time the data is input into/called by the user defined function, it can be treated as a reactive element?
Thank you for you help!
Upvotes: 1
Views: 785
Reputation: 4072
To be able to pass a reactive
to a function, you need to pass it without brackets.
data_chart(data_1, c('Plant', 'Type', 'Treatment', 'Conc', 'Uptake'))
You can use it within the function with the name of the argument + brackets: shiny_data()
data_chart <- function(shiny_data, col_names){
shinyApp(
ui = fluidPage(
DT::dataTableOutput("results")
),
server = function(input, output, session) {
output$results <- DT::renderDataTable(
datatable(
shiny_data(),
filter = 'top',
colnames = col_names,
rownames = FALSE,
options = list(
dom = 'lptpi',
scrollY = '',
order = list(3, 'desc')
)
)
)
}
)
}
Upvotes: 2