Shiny conditionalPanel conditions based on NULL values in R?
Asked Answered
W

2

10

I am writing a Shiny application that will query a database a few times. The queries may take some time, so I am using actionButton to allow the user to control when they are started.

The general flow of the application is:

  • User loads page, pushes button to load in available choices from the database.
  • User selects a row from the available choices, and then kicks off a larger query that will take longer.
  • When the query is done, the user will get nice visualizations and other such things.

I know that you can allow the user to select rows from a DataTable using the selection option, and I am currently using the development build so that single-selection can be enabled. My problem is figuring out how to hide certain conditional panels until the user has made a choice. As far as I can tell, the value of the choice is stored in input$[data frame name]_rows_selected. But, until the values are selected, this value is either NULL, or does not exist.

I cannot figure out how to pass to the condition argument of conditionalPanel() a condition which reflects the internal R logic. I've written a minimal working example below which shows the behavior to which I'm referring.

library(shiny)
library(DT)

# Create sample data
df_sample_data <- data.frame(name = c("John Smith","Jane Cochran","Belle Ralston","Quincy Darcelio"),
                             color = c("Red","Blue","Red","Green"),
                             age = c(25,52,31,29))

ui <-
    fluidPage(

        titlePanel("The Title!"),

        sidebarPanel(

            h1("Load Data"),
            actionButton("load_data","Load Data"),
            br(),
            conditionalPanel(

                h1("Do Thing"),
                actionButton("do_thing","Do Thing"),
                condition = "input.df_data_rows_selected !== undefined")
            ),

        mainPanel(

            dataTableOutput("df_data"),
            conditionalPanel(

                tableOutput("row_selected"),
                condition = "input.df_data_rows_selected !== undefined")
            )
    )

server <-
    function(input, output) {

        # This function loads the data (in reality it is a server operation)
        uFunc_ReactiveDataLoad <- eventReactive(eventExpr = input$load_data,valueExpr = {

            df_data <- df_sample_data
            return(list(display_table = datatable(data = df_data[c("name","age")],
                                                  options = list(dom = "tip"),
                                                  filter = "top",
                                                  selection = "single",
                                                  colnames = c("Person Name" = "name",
                                                               "Person Age" = "age")),
                        data_table = df_data))
        })
        output$df_data <- renderDataTable(expr = uFunc_ReactiveDataLoad()$display_table)
        output$row_selected <- renderTable(expr = uFunc_ReactiveDataLoad()$data_table[input$df_data_rows_selected,])
    }

shinyApp(ui = ui, server = server)

In the current setup, which uses input.df_data_rows_selected !== undefined, the panels are hidden until the data is loaded using the first actionButton. But, I need them to remain hidden unless the user has selected a row. I have tried other things such as:

  • input.df_data_rows_selected !== null
  • input.df_data_rows_selected !== 'null'
  • input.df_data_rows_selected !== ''
  • input.df_data_rows_selected !== 'NULL'

...and so on, but I have had no luck. How does the NULL value in R get represented in the JavaScript used for the condition argument to conditionalPanel()?

Wheelman answered 14/3, 2016 at 19:40 Comment(0)
P
13

condition = "(typeof input.df_data_rows_selected !== 'undefined' && input.df_data_rows_selected.length > 0)" for both entries seems to work.

Pyrogallol answered 14/3, 2016 at 19:58 Comment(6)
This doesn't seem to work for me. Like before, the "Do Thing" panel appears once the button "Load Data" is pushed, but before a row is selected.Wheelman
Man, this is a tough one... condition = 'input.df_data_rows_selected.length > 0') gets really close, but not quite there...Pyrogallol
@Wheelman I got it... gotta check for the array being undefined and length > 0. I've edited my answerPyrogallol
It works! If you want to add a little bit to the answer explaining why it works that would probably help other JS neophytes like me.Wheelman
I started to try to come up with an explanation, but it would be just speculation. I'm likely as much of a javascript neophyte as you. I was just googling for info on testing for empty arrays in javascript and this was one thing I found. I wish I could do better, but it was honestly just trial and error for me.Pyrogallol
Works for me! If you ever come through Madison hit me up and I'll buy you a beer or something. :)Wheelman
P
3
condition = "(typeof input.df_data_rows_selected === null")

If anyone is stumbling upon this issue a few years later...

Pablo answered 24/8, 2021 at 13:21 Comment(2)
Could you please explain the reason for the triple = sign?Cr
@Cr triple equal ("===") compare raw references and skip overloading operator ("==").Pablo

© 2022 - 2024 — McMap. All rights reserved.