Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Retain the values in the Check Box in R Shiny App?

I am trying to create a Shiny App. In this particular app i have a set of Radio buttons where choosing one will display a set of options below as Check Boxes and Choosing another radio button will choose other set of options. Kindly find the UI and the Server Code below.

library(shiny)
library(shinydashboard)
library(shinyWidgets)

d <-
  data.frame(
    year = c(1995, 1995, 1995, 1996, 1996, 1996, 1997, 1997, 1997),
    Product_Name = c(
      "Table",
      "Chair",
      "Bed",
      "Table",
      "Chair",
      "Bed",
      "Table",
      "Chair",
      "Bed"
    ),
    Product_desc = c("X", "X", "X", "Y", "Y", "Y", "Z", "Z", "Z"),
    Cost = c(1, 2, 3, 4, 2, 3, 4, 5, 6)
  )

ui <- shinyUI(fluidPage(
  useShinydashboard(),
  tabPanel(
    "Plot",
    sidebarLayout(
      sidebarPanel(
        radioButtons(
          "Choose",
          "Choose One",
          c("Year" = "p", "Numbers" = "l")
        ),
        uiOutput('checkbox'),
        #width = 2,
        position = "bottom"),
      mainPanel(uiOutput("graph"))

    )
  )
))

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

  output$graph <- renderUI({
    # create tabPanel with datatable in it
    req(input$year)
    tabPanel("Plots",
             fluidRow(lapply(as.list(paste0("plot", seq_along(input$year))), plotOutput)))

  })

  output$checkbox <- renderUI({
    if (input$Choose == "p") {
      checkboxGroupInput("Cross",
                         "Year",
                         choices = (unique(d$year)))

    } else{
      checkboxGroupInput("Cross_1",
                         "Numbers",
                         choices = c("1","2","3"))
    }

  })

}

shinyApp(ui, server)

Now the challenge which I am facing is when i choose the "Year" Radio button the year values get displayed as check boxes and when i select the check boxes a corresponding graphs get displayed in the main panel (I have not given the code over here). Now when I choose the "Number" Radio Button the correct check box options are getting displayed. But when I move back to the "Year" Radio button. The already selected check box values are not retained so the user needs to check the boxes again to get the corresponding graphs.

The choices in CheckboxGroupInput() are dynamic in my case. So i will not be able to give this choices in UI(). Also i tried using updateCheckboxGroupInput() which failed. By doing some investigations in to the code once again, I understood that the place where the issue is taking place is this part of the code.

  output$checkbox <- renderUI({
    if (input$Choose == "p") {
      checkboxGroupInput("Cross",
                         "Year",
                         choices = (unique(d$year)))

    } else{
      checkboxGroupInput("Cross_1",
                         "Numbers",
                         choices = c("1","2","3"))
    }

  })

Please suggest me on how to retain the values in the checkbox even when the another radio button is chosen. Also please be informed that the options of Check boxes under each radio button will change according to the options the user has selected in the previous tab. So i use observe function to obtain the corresponding check boxes.

like image 375
David Chris Avatar asked Apr 23 '20 08:04

David Chris


2 Answers

You could store the values of the years you attempt to keep in reactive values.

  global <- reactiveValues(years = NULL)

  observeEvent(input$Cross, {
    global$years <- input$Cross
  })

Then you make your dynamic ui dependent on the reactive values:

checkboxGroupInput(
  "Cross",
  "Year",
  choices = (unique(d$year)),
  selected = global$years
)

Reproducible example:

library(shiny)
library(shinydashboard)
library(shinyWidgets)

d <-
  data.frame(
    year = c(1995, 1995, 1995, 1996, 1996, 1996, 1997, 1997, 1997),
    Product_Name = c(
      "Table",
      "Chair",
      "Bed",
      "Table",
      "Chair",
      "Bed",
      "Table",
      "Chair",
      "Bed"
    ),
    Product_desc = c("X", "X", "X", "Y", "Y", "Y", "Z", "Z", "Z"),
    Cost = c(1, 2, 3, 4, 2, 3, 4, 5, 6)
  )

ui <- shinyUI(fluidPage(
  useShinydashboard(),
  tabPanel(
    "Plot",
    sidebarLayout(
      sidebarPanel(
        radioButtons(
          "Choose",
          "Choose One",
          c("Year" = "p", "Numbers" = "l")
        ),
        uiOutput('checkbox'),
        #width = 2,
        position = "bottom"),
      mainPanel(uiOutput("graph"))

    )
  )
))

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

  global <- reactiveValues(years = NULL)

  observeEvent(input$Cross, {
    global$years <- input$Cross
  })

  output$graph <- renderUI({
    # create tabPanel with datatable in it
    req(input$year)
    tabPanel("Plots",
             fluidRow(lapply(as.list(paste0("plot", seq_along(input$year))), plotOutput)))

  })

  output$checkbox <- renderUI({
    if (input$Choose == "p") {
      checkboxGroupInput("Cross",
                         "Year",
                         choices = (unique(d$year)),selected = global$years)

    } else{
      checkboxGroupInput("Cross_1",
                         "Numbers",
                         choices = c("1","2","3"))
    }

  })

}

shinyApp(ui, server)

I think the shinyjs hide/show variant of Ash is also interesting. I havent tested it but i assume you could just replace the static ui with a dynamic there (?).

like image 89
Tonio Liebrand Avatar answered Nov 14 '22 23:11

Tonio Liebrand


I'd suggest showing/hiding the checkboxs rather than using renderUI. This way they will retain their settings even when they are not shown.

shinyjs is a popular package that can do this for us. I've created a minimal example based on the above code to show this in action:

library(shiny)
library(shinyjs)

ui <- shinyUI(fluidPage(

    useShinyjs(),

    radioButtons("radio_choose", "Choose One", choices = c("Year", "Numbers")),

    checkboxGroupInput("checkbox_years", "Year", choices = c(1995, 1996, 1997, 1997)),

    checkboxGroupInput("checkbox_numbers", "Numbers", choices = c(1, 2, 3))

))

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

    #Observe the radio buttons (runs when the radio button changes)
    observeEvent(input$radio_choose, {

        if(input$radio_choose == "Year") {

            shinyjs::show("checkbox_years")
            shinyjs::hide("checkbox_numbers")

        }

        if(input$radio_choose == "Numbers") {

            shinyjs::hide("checkbox_years")
            shinyjs::show("checkbox_numbers")

        }

    })

}

shinyApp(ui, server)
like image 38
Ash Avatar answered Nov 14 '22 22:11

Ash