【问题标题】:swap pickerInput on a button press in Shiny在 Shiny 中按下按钮时交换 pickerInput
【发布时间】:2022-01-05 17:10:51
【问题描述】:

我需要在按下按钮时从下拉输入中更新/反转两个输入。在我按下交换按钮 (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

【问题讨论】:

  • observe 块是否会触发?我猜你需要observe(input$reverse_xz, {...})
  • 嗨,杰夫,感谢您的帮助!我确实尝试过observeEvent(input$reverse_xz, {...}),它起作用了,但没有做太多。执行您推荐的操作时,我收到 Warning: Error in : Can't access reactive value 'reverse_xz' outside of reactive consumer. i Do you need to wrap inside reactive() or observe()? 58: &lt;Anonymous&gt; 并且应用程序崩溃。
  • 我有一个关于你想要什么的问题。您是否真的想要:(1)在pickerInputs之间切换已选择的选项? (2) 限制选项,所以如果在pickerInput X中选择了选项A,那么在pickerInput Z中就不会显示选项A了?因为我从一个小时开始考虑这个问题,并认为不可能同时拥有这两者,因为它会导致无限循环。
  • 嗨@gss- 抱歉,我不打算浪费任何人的时间和精力。我应该更清楚。 (1) 是的,一旦点击交换按钮,切换已经选择的pickerInputs。 (2) 是的,所有下拉选项(包括选中的)都需要反转。我们必须从向量中删除选定选项的原因是为了防止在 x 和 z 输入中重复选择。我以为我们可以通过my_vars[!(my_vars %in% input$...)] 来实现这一点?!我没有预见到更新它会造成无限循环。我欢迎任何建议或替代实现。
  • 不,没关系。当我写“一个小时”时,我并没有任何负面的意思:)

标签: r shiny shinydashboard shiny-server shiny-reactivity


【解决方案1】:

看看这个并检查它是否适合你:

#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,因此两者都将“未选择任何内容”作为用户出现问题(或她/他做错了什么)的标志。但是,“未选择”就像 NULL,我们不能在 if 中使用像这样的 NULL == "something" NULL,所以我正在使用 length(input$) &gt; 0 检查某些输入是否为 NULL,因为 NULL 的长度为 0。你可以使用!is.null(input$) 而不是length(input$) &gt; 0,也许你应该使用它,因为它可能更具可读性,但我将把这个决定留给你。

【讨论】:

  • 感谢您的帮助!您的解决方案效果很好,您的详细解释很棒:)
猜你喜欢
  • 2023-03-16
  • 2021-07-03
  • 2021-05-26
  • 2021-08-02
  • 2014-02-03
  • 1970-01-01
  • 2017-08-09
  • 2017-12-31
  • 2016-10-22
相关资源
最近更新 更多