Hoju
Hoju

Reputation: 139

DataTable with no data

It must be late because I can't figure this out. When I run the Shiny app below the DataTable appears blank.

Could you help me spot my mistake please?

As far as I know df_filtered should return df if no input is selected. And the it is called as a reactive function by renderDataTable.

library(shiny)
library(shinydashboard)
library(DT)
library(dplyr)

# Test data
LANZ <- c(1,2,3,4,5)
TIPO <- c('V5', 'V5', 'V10', 'V10', 'V10')
PROY <- c('1', '2', '2', '2', '3')
YEAR <- c(2019, 2020, 2020, 2020, 2019)
df <- data.frame(LANZ, TIPO, PROY, YEAR)
colnames(df)[1] <- "LANZ"
colnames(df)[2] <- "TIPO"
colnames(df)[3] <- "PROY"
colnames(df)[4] <- "YEAR"

ui <- dashboardPage(
  dashboardHeader(title = "Title"),
  dashboardSidebar(
    sidebarMenu(
    )),
  dashboardBody(
    
    wellPanel(
      fluidRow(
        column(4, selectInput("idYearD", "", selected=NULL, multiple=FALSE, choice=c('Year' = '', c("2019","2020")))),
        column(4, selectInput("idTipo", "", selected=NULL, multiple=FALSE, choice=c('Tipo' = '', c("V5","V10")))),
        column(4, selectInput("idProy", "", selected=NULL, multiple=FALSE, choice=c('Proy' = '', c("1","2","3")))
        )),

      fluidRow(
        column(12, DT::dataTableOutput('dataTable'))
      ))
))


server <- function(input, output) {
  
  df_filtered <- reactive({
    
    data_df <- df
    if (!is.null( input$idYearD ) ) {
      data_df <- data_df %>% filter(YEAR %in% input$idYearD)
    }
    if (!is.null( input$idTipo )) {
      data_df <- data_df %>% filter(TIPO %in% input$idTipo)
    }
    if (!is.null( input$idProy )) {
      data_df <- data_df %>% filter(PROY %in% input$idProy)
    }
    data_df
  })
  
  output$dataTable <- DT::renderDataTable(
    df_filtered()
  )
}

shinyApp(ui = ui, server = server)

Best regards.

Upvotes: 1

Views: 295

Answers (1)

r2evans
r2evans

Reputation: 160862

Up front: is.null is not catching the fact that input$idYearD can be (and starts as) the empty string, "". Use either !is.null(.) && nzchar(.) or shiny::isTruthy(.).

Side note: input$idYearD is a string, whereas your YEAR is a number. R is doing the intuitive thing by inferring the comparison (casting/coercing), but you need to be aware that this is doing a string comparison, not a numeric one. It works here. This is more impactful when dealing with floating-point and/or order of things, as < and > (and sort and order ...) are doing alphabetic comparisons ... "11" < 2 is counter-intuitively true.


What I did was interject browser() in your df_filtered reactive block:

  df_filtered <- reactive({
    browser()
    # ...
  })

From there, on execution, testing

!is.null( input$idYearD )
# [1] TRUE
input$idYearD
# [1] ""

So perhaps this block instead:

  df_filtered <- reactive({
    
    data_df <- df
    if ( isTruthy( input$idYearD ) ) {
      data_df <- data_df %>% filter(YEAR %in% input$idYearD)
    }
    if ( isTruthy( input$idTipo ) ) {
      data_df <- data_df %>% filter(TIPO %in% input$idTipo)
    }
    if ( isTruthy( input$idProy ) ) {
      data_df <- data_df %>% filter(PROY %in% input$idProy)
    }
    data_df
  })

Alternatively (and more compactly), you could do:

  df_filtered <- reactive({
    df %>%
      filter(
        !isTruthy( input$idYearD ) | YEAR %in% input$idYearD,
        !isTruthy( input$idTipo ) | TIPO %in% input$idTipo,
        !isTruthy( input$idProy ) | PROY %in% input$idProy
      )
  })

Edited to remove is.null, since isTruthy(NULL) is the same as !is.null(NULL).

If for some reason in your future isTruthy doesn't quite meet all of your needs, your original code could be augmented for just a string-specific comparison, as in

    if (!is.null( input$idYearD ) && nzchar( input$idYearD )) {

Upvotes: 3

Related Questions