LGe
LGe

Reputation: 516

Shiny: how to make a reactive input for a conditional filter in this case?

Recently I was changing the options of a DT::datatable and because I had to use formatCurrency, I was taking the datatable function outside of renderDataTable. In this case my dynamic filter by the Alias column of the input object selected by selectInput is not working anymore.

The error suggests to wrap the expression into reactive or observeEvent. I did try some approaches which all failed. Maybe someone does get this right fast:

# shiny lib
library(shiny)
library(shinydashboard)
# core
suppressPackageStartupMessages(library(tidyverse))
suppressPackageStartupMessages(library(DT))

#### UI 

ui <- dashboardPage(
  dashboardHeader(title = "TEST"),
  dashboardSidebar(
    sidebarMenu(id = "tabs",
                menuItem("Inspection",
                         tabName = "analyze"
                        )
             )
  ),
  dashboardBody(
    tabItems(
      tabItem(tabName = "analyze",
              selectInput(inputId = "id",
                          label = "Select",
                          choices = "",
                          selected = ""),
              mainPanel(width = 100, 
                        fluidPage(
                          fluidRow(dataTableOutput("ts_kpi1.1")
                          )
                      )
                  )
              )
          )
     )
)


#### SERVER
    
  server <- function(input, output, session) {

  data <- tibble(value = c(c(10000.33,15000.55),c(12000.99,33005.44)),
                 Alias = c(rep("A",2),rep("B",2))
  )
  updateSelectInput(session ,
                    "id",
                    choices = unique(data$Alias)
  )
  df_kpi1 <- data %>% 
    dplyr::filter(Alias == input$id) %>%
    summarise(Mean = mean(value),
              Median = median(value)
    ) %>% as_tibble() %>% 
    mutate_if(is.numeric, ~round(., 0)
              )
  DT_kpi1 <- datatable(df_kpi1,         
                     options = list(
                       scrollX = FALSE,
                                    autoWidth = TRUE,
                                    bFilter = 0,
                                    bInfo = FALSE,
                                    bPaginate = FALSE,
                                    lengthChange = FALSE,
                                    columnDefs = list(list(searchable = FALSE, targets = "_all"),
                                                      list(targets = c(0), visible = TRUE),
                                                      list(searching = FALSE),
                                                      list(ordering=F)
                                                     )
                                                   ),
                                   rownames = FALSE ) %>% 
                                   formatCurrency(columns = c(1:2), currency = "", interval = 3, mark = ".")
  output$ts_kpi1.1 <- DT::renderDataTable({
    DT_kpi1
  }) 
}
runApp(list(ui = ui, server = server),launch.browser = TRUE)

Upvotes: 0

Views: 852

Answers (1)

fschier
fschier

Reputation: 299

As you correctly assumed in your question R pretty much gives you the answer in the error message:

Input `..1` is `Alias == input$id`.
x Can't access reactive value 'id' outside of reactive consumer.
i Do you need to wrap inside reactive() or observe()?

you cant access the value within input$id outside of a reactive context. Just wrap your assignment of df_kpi1 into a reactive, e.g.:

df_kpi1 <- reactive(data %>%
      ...
      ...
      )

This should solve your issue.

EDIT: Your example

# shiny lib
library(shiny)
library(shinydashboard)
# core
suppressPackageStartupMessages(library(tidyverse))
suppressPackageStartupMessages(library(DT))

#### UI 

ui <- dashboardPage(
  dashboardHeader(title = "TEST"),
  dashboardSidebar(
    sidebarMenu(id = "tabs",
                menuItem("Inspection",
                         tabName = "analyze"
                )
    )
  ),
  dashboardBody(
    tabItems(
      tabItem(tabName = "analyze",
              selectInput(inputId = "id",
                          label = "Select",
                          choices = "",
                          selected = ""),
              mainPanel(width = 100, 
                        fluidPage(
                          fluidRow(dataTableOutput("ts_kpi1.1")
                          )
                        )
              )
      )
    )
  )
)


#### SERVER

server <- function(input, output, session) {
  
  data <- tibble(value = c(c(10000.33,15000.55),c(12000.99,33005.44)),
                 Alias = c(rep("A",2),rep("B",2))
  )
  updateSelectInput(session ,
                    "id",
                    choices = unique(data$Alias)
  )
  DT_kpi1 <- reactive({
    
    
    df_kpi1 <- data %>% 
    dplyr::filter(Alias == input$id) %>%
    summarise(Mean = mean(value),
              Median = median(value)
    ) %>% as_tibble() %>% 
    mutate_if(is.numeric, ~round(., 0)
    )
    
  DT_kpi1 <- datatable(df_kpi1,         
                       options = list(
                         scrollX = FALSE,
                         autoWidth = TRUE,
                         bFilter = 0,
                         bInfo = FALSE,
                         bPaginate = FALSE,
                         lengthChange = FALSE,
                         columnDefs = list(list(searchable = FALSE, targets = "_all"),
                                           list(targets = c(0), visible = TRUE),
                                           list(searching = FALSE),
                                           list(ordering=F)
                         )
                       ),
                       rownames = FALSE ) %>% 
    formatCurrency(columns = c(1:2), currency = "", interval = 3, mark = ".")
  DT_kpi1
  })
  
  
  output$ts_kpi1.1 <- DT::renderDataTable({
    DT_kpi1()
  }) 
}
runApp(list(ui = ui, server = server),launch.browser = TRUE)

Upvotes: 1

Related Questions