2

I would like to pass data (static) from ui to the server in a shiny module. For a concrete example of the issue I am dealing with consider the app below. I want to be able to use the button to rotate through the radio input. However, because I do not have the choices for the radioInput in the server I am unable to update the radioInput with the next option.

There are a few possible solutions of course. The first is to pass the list of the radioInput choices to the server function. I would like to avoid passing this data in two places ui and server. The second option is to use renderUI and pass the choices list that way from server to ui, but given that there is no dynamic aspect to the UI this is also undesirable.

Is there a clean way to pass a static data from ui to server?

library(shiny)

rotatingRadioInput <- function(id, label, choices = c('A' = 'a', 'B' = 'b'), selected = 'a') {
  labelNames <- names(choices)
  values <- unname(choices)

  tagList(
    radioButtons(NS(id, "radio"), 
                 label = NULL,
                 choiceValues = values,
                 choiceNames = labelNames,
                 selected = selected
    ),
    actionButton(NS(id, 'rotate'), 'rotate')
  )
}

rotatingRadioServer <- function(id) {
  moduleServer(id, function(input, output, session) {
    observeEvent(input$rotate, {
      updateRadioButtons(session, "radio", selected = "next radio option")
    })
    
    reactive({
      input$radio
    })
  })
}

rotatingRadioApp <- function() {
  ui <- fluidPage(
    rotatingRadioInput("rotate"),
    textOutput("value")
  )
  server <- function(input, output, server) {
    rotatingValue <- rotatingRadioServer("rotate")
    output$value <- renderText(paste0("Selected: ", rotatingValue()))
  }
  
  shinyApp(ui, server)
}
student
  • 1,001
  • 2
  • 12
  • 24

1 Answers1

0

One way to do it is to use a hidden selectInput with all the choices selected. Shinyjs package is required. Try this

library(shiny)
library(shinyjs)

rotatingRadioInput <- function(id, label, choices = c('A' = 'a', 'B' = 'b'), selected = 'a') {
  labelNames <- names(choices)
  values <- unname(choices)

  tagList(
    radioButtons(NS(id, "radio"),
                 label = NULL,
                 choiceValues = values,
                 choiceNames = labelNames,
                 selected = selected
    ),
    actionButton(NS(id, 'rotate'), 'rotate'),
    hidden(selectInput(NS(id,"mychoices"),"", choices=values, selected=values, multiple=TRUE))
  )
}

rotatingRadioServer <- function(id) {
  moduleServer(id, function(input, output, session) {

    observeEvent(input$rotate, {
      choices <- input$mychoices
      newchoices <- choices[!(choices %in% input$radio)]
      updateRadioButtons(session, "radio", selected = newchoices[1])
    })
    reactive({input$radio})
    # return(reactive({input$radio}))
  })
}

#rotatingRadioApp <- function() {
  ui <- fluidPage(
    useShinyjs(),
    rotatingRadioInput("rotate"),
    textOutput("value")
  )
  server <- function(input, output, server) {
    rotatingValue <- rotatingRadioServer("rotate")
    #observe({print(rotatingValue())})
    output$value <- renderText(paste0("Selected: ", rotatingValue()))
  }

  shinyApp(ui, server)
#}

#rotatingRadioApp()

output

YBS
  • 19,324
  • 2
  • 9
  • 27
  • I was hopping there is a nice way to get this done perhaps being able to extract the values from session. – student Sep 24 '21 at 16:06
  • @YBS , Is there a way to pass more complex objects like dataframes? – GitHunter0 Jan 07 '22 at 20:33
  • @GitHunter0, Sure. Please post it as a new question in SO. Someone can help you. – YBS Jan 09 '22 at 21:59
  • Thank you @YBS , I just posted this question https://stackoverflow.com/questions/70660603/how-to-pass-a-data-frame-from-ui-to-server-in-an-r-shiny-module – GitHunter0 Jan 11 '22 at 01:18