Warm tip: This article is reproduced from stackoverflow.com, please click
flexdashboard r r-markdown shiny

Pass reactive() element into user defined function that makes a shinyApp()

发布于 2020-03-27 10:21:59

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!

Questioner
Joe Short
Viewed
119
GyD 2019-07-04 00:19

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()

Full data_chart function:

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')
          )
        )
      )
    }
  )
}

Output

output