在 Shiny 中按按钮交换 pickerInput

swap pickerInput on a button press in Shiny

我需要 update/reverse 按下按钮时下拉输入中的两个输入。当我按下交换按钮 (reverse_xz) 时,它会做出反应,但是 updatePickerInput 不会切换我的 x 和 z 输入。

我想要的功能是,一旦单击交换按钮,就可以切换已经选择的 pickerInputs。然后,所有下拉选项(包括选中的)都需要反转。我们必须从矢量中删除所选选项的原因是为了防止在 x 和 z 输入中重复选择。

我不确定是否必须在服务器端渲染 pickerInput ui?!

下面是我的代码:


#global.R
library(shiny)
library(shinydashboard)
library(shinydashboardPlus)
library(shinyWidgets)
library(shinyjs)

#variable labels
my_vars <- c("None"= "NONE",
             "All" = "all_all",
             "Pro" = "Pro_",
             "Locomania" = "locomania_Type",
             "Racer" = "race")

#ui.R
ui <- shinydashboardPlus::dashboardPage(
  
  header = shinydashboardPlus::dashboardHeader( ),
  
  body = shinydashboard::dashboardBody(  box(textOutput("inputs") ) ),
  
  sidebar = shinydashboardPlus::dashboardSidebar(
    
  
    shinyWidgets::pickerInput(
      inputId = "xvar",
      label = "X Axis: ", 
      choices = my_vars,
      options = list(
        size = 5),
      multiple = FALSE,
      selected = "all_all"
    ),
    
    # Button to reverse the choices
    
    shiny::fluidRow(
      shiny::column(12, offset = 4,
                    shinyWidgets::actionBttn(
                      inputId = "reverse_xz",
                      label = "", 
                      style = "simple",
                      color = "primary",
                      icon = icon("retweet")
                    )
      )
    ),
    
    
    shinyWidgets::pickerInput(
      inputId = "zvar",
      label = "Z Axis: ", 
      choices = my_vars,
      options = list(
        size = 5),
      multiple = FALSE,
      selected = "race"
    )
    
  )
)

#server.R
server <- function(input, output, session) {
  
  # 
  observe({
    
    if(!is.null(input$reverse_xz))
      
      shinyWidgets::updatePickerInput(session, "zvar", 
                                      choices = my_vars[!(my_vars %in% input$xvar)], 
                                      selected = isolate(input$zvar) )
    
    shinyWidgets::updatePickerInput(session, "xvar", 
                                    choices = my_vars[!(my_vars %in% input$zvar)], 
                                    selected = isolate(input$xvar) )
  })
  
  
  # These observers remove the selected choices so both pickers are unique
  observe({
    
    if(!is.null(input$zvar))
      
      shinyWidgets::updatePickerInput(session, "xvar", 
                                      choices = my_vars[!(my_vars %in% input$zvar)], 
                                      selected = isolate(input$xvar) )
  })
  
  observe({
    if(!is.null(input$xvar))
      
      shinyWidgets::updatePickerInput(session, "zvar", 
                                      choices = my_vars[!(my_vars %in% input$xvar)], 
                                      selected = isolate(input$zvar) )
  })
  
  
  # output inputs
  output$inputs <- renderText({ paste0("x var: ", input$xvar,
                                       "\n\n\n z var:", input$zvar,
                                     "\n\n\nreverse press: ", input$reverse_xz) })
  
}


shiny::shinyApp(ui= ui, server= server)

提前谢谢你。我看过一些相关的帖子,但是他们不能给我太多帮助:

  1. Updatepickerinput with change in pickerinput in Shiny
  2. updatePickerInput not updating values after changing tabs in R shiny
  3. update pickerInput by using updatePickerInput in shiny

看看这个,看看它是否适合你:

#global.R
library(shiny)
library(shinydashboard)
library(shinydashboardPlus)
library(shinyWidgets)
library(shinyjs)

#variable labels
my_vars <- c("None"= "NONE",
             "All" = "all_all",
             "Pro" = "Pro_",
             "Locomania" = "locomania_Type",
             "Racer" = "race")

#ui.R
ui <- shinydashboardPlus::dashboardPage(
  
  header = shinydashboardPlus::dashboardHeader( ),
  
  body = shinydashboard::dashboardBody(  box(textOutput("inputs") ) ),
  
  sidebar = shinydashboardPlus::dashboardSidebar(
    
    
    shinyWidgets::pickerInput(
      inputId = "xvar",
      label = "X Axis: ", 
      choices = my_vars,
      options = list(
        size = 5),
      multiple = FALSE,
      selected = "all_all"
    ),
    
    # Button to reverse the choices
    
    shiny::fluidRow(
      shiny::column(12, offset = 4,
                    shinyWidgets::actionBttn(
                      inputId = "reverse_xz",
                      label = "", 
                      style = "simple",
                      color = "primary",
                      icon = icon("retweet")
                    )
      )
    ),
    
    
    shinyWidgets::pickerInput(
      inputId = "zvar",
      label = "Z Axis: ", 
      choices = my_vars,
      options = list(
        size = 5),
      multiple = FALSE,
      selected = "race"
    )
    
  )
)

#server.R
server <- function(input, output, session) {
  
  # 
  observeEvent(input$reverse_xz, {
    
    shinyWidgets::updatePickerInput(session, "zvar", 
                                    choices = my_vars[!(my_vars %in% input$zvar)], 
                                    selected = input$xvar)
    
    shinyWidgets::updatePickerInput(session, "xvar", 
                                    choices = my_vars[!(my_vars %in% input$xvar)], 
                                    selected = input$zvar)
  })
  
  observe({
    
    if (input$xvar == input$zvar && (length(input$zvar) > 0 && length(input$xvar) > 0)) {
      shinyWidgets::updatePickerInput(session, "zvar", 
                                      selected = "")
      
      shinyWidgets::updatePickerInput(session, "xvar", 
                                      selected = "")
      
    }
    
  })
  
  # output inputs
  output$inputs <- renderText({ paste0("x var: ", input$xvar,
                                       "\n\n\n z var:", input$zvar,
                                       "\n\n\nreverse press: ", input$reverse_xz) })
  
}

shiny::shinyApp(ui= ui, server= server)

我想也许这需要解释一下:

if (input$xvar == input$zvar && (length(input$zvar) > 0 && length(input$xvar) > 0))

因此,当用户选择两个相同的输入时,我们将更新 pickerInputs,因此两者都将“未选择”作为用户出现问题(或 she/he 做错了什么)的标志.但是,“未选择”就像 NULL,我们不能像 NULL == "something"if 中使用 NULL,所以我正在使用 length(input$) > 0 检查某些输入是否为 NULL,因为长度NULL 是 0。您可以使用 !is.null(input$) 而不是 length(input$) > 0,也许您应该使用它,因为它可能更具可读性,但我将这个决定留给您。