3

我正在构建一个闪亮的应用程序,它根据 selectInput() 值更新 checkboxGroupInput() 。我还想存储选择/取消选择的值,以便在我重新选择输入值时它们看起来相同。为此,我使用反应值来存储选择。

这是一个玩具示例:

library(shiny)

letters = c('A','B','C','D','E','F','G','H','I','J','K','L')

words = list( "A" = c("apples","aardvark","alabama"),
              "B" = c("banana","baltimore","beehive"),
              "C" = c("catastrophe","cantalope"),
              "D" = c("dinosaur","dairy","dolphin"),
              "E" = c("eager","elephant","ecumenical"),
              "F" = c("fleming","florida","flight"),
              "G" = c("gator","greater","gait"),
              "H" = c("HI"),
              "I" = c("igloo","ignominious","interesting"),
              "J" = c("jogging","jumpsuit"),
              "K" = c("kellog","kangaroo"),
              "L" = c("lemon","lime","lemonjello"))


ui <- fluidPage(

    selectInput("letter","Choose Letter",choices=letters,selectize=F), 

  # Initiate check box group
    checkboxGroupInput('words_by_letter',label='Select Your Favorite Words',choices = c(1))

)


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

  v_selected <- reactiveValues(
        "A" = c("apples","aardvark","alabama"),
        "B" = c("banana","baltimore","beehive"),
        "C" = c("catastrophe","cantalope"),
        "D" = c("dinosaur","dairy","dolphin"),
        "E" = c("eager","elephant","ecumenical"),
        "F" = c("fleming","florida","flight"),
        "G" = c("gator","greater","gait"),
        "H" = c("HI"),
        "I" = c("igloo","ignominious","interesting"),
        "J" = c("jogging","jumpsuit"),
        "K" = c("kellog","kangaroo"),
        "L" = c("lemon","lime","lemonjello"))

  observeEvent(input$letter,{         
    updateCheckboxGroupInput(session,
       inputId  = "words_by_letter",
       choices  = words[[input$letter]], 
       selected = v_selected[[input$letter]])

  })

  observeEvent(input$words_by_letter,{ 
    v_selected[[input$letter]] = input$words_by_letter
  })

}


shinyApp(ui = ui, server = server)

在大多数情况下,这工作正常。但是,如果您快速滚动输入(通过按住箭头按钮),最终某些复选框组将全部取消选中。我假设这与 Javascript 的反应速度和通信速度有关,但我不知道如何解决它。

注意:我也尝试为每个“字母”使用单独的条件面板,但这会大大增加我的应用程序的加载时间,所以我不想使用该策略。

4

1 回答 1

2

这似乎是一个竞争条件,input$letter更新太快,shinyServer 跟不上它,它试图用不一致的数据更新反应状态。例如,它尝试用“J”选项覆盖“I”单词,然后输入选择器不再起作用。我认为根本原因不容易解决。

input$letter但是,一种解决方法是仅在您拥有且input$words_by_letter一致的值时才更新您的反应状态。

根据您的实际数据,这可能会或可能不会起作用 - 您需要组织数据,以便有一个可以测试的一致性条件并使用它来保护您的更新。在您的玩具示例中,我可以将选择的单词与您初始化选择的单词进行比较 - 我利用了这一点。

我本可以使用比较input$words_by_letter匹配中单词的第一个字母input$letter,但这似乎太专业了 - 这样,将所选数据与选择初始化进行比较更有可能概括。

这是代码:

library(shiny)

letters = c('A','B','C','D','E','F','G','H','I','J','K','L')
words = list( "A" = c("apples","aardvark","alabama"),
              "B" = c("banana","baltimore","beehive"),
              "C" = c("catastrophe","cantalope"),
              "D" = c("dinosaur","dairy","dolphin"),
              "E" = c("eager","elephant","ecumenical"),
              "F" = c("fleming","florida","flight"),
              "G" = c("gator","greater","gait"),
              "H" = c("HI"),
              "I" = c("igloo","ignominious","interesting"),
              "J" = c("jogging","jumpsuit"),
              "K" = c("kellog","kangaroo"),
              "L" = c("lemon","lime","lemonjello"))
ui <- fluidPage(

  selectInput("letter","Choose Letter",choices=letters,selectize=F), 

  # Initiate check box group
  checkboxGroupInput('words_by_letter',label='Select Your Favorite Words',choices = c(1))
)

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

  v_selected <- reactiveValues(
    "A" = c("apples","aardvark","alabama"),
    "B" = c("banana","baltimore","beehive"),
    "C" = c("catastrophe","cantalope"),
    "D" = c("dinosaur","dairy","dolphin"),
    "E" = c("eager","elephant","ecumenical"),
    "F" = c("fleming","florida","flight"),
    "G" = c("gator","greater","gait"),
    "H" = c("HI"),
    "I" = c("igloo","ignominious","interesting"),
    "J" = c("jogging","jumpsuit"),
    "K" = c("kellog","kangaroo"),
    "L" = c("lemon","lime","lemonjello"))

  observeEvent(input$letter,{

    v_selected$last <- input$letter
    updateCheckboxGroupInput(session,
                             inputId  = "words_by_letter",
                             choices  = words[[input$letter]], 
                             selected = v_selected[[input$letter]])
  })
  overwriteIfConsistent <- function(selector,newvals,initwords){
    # only overwrite if the new values are int the initial list
    initwords1 <- initwords[[selector]] 
    truthvek <- newvals %in% initwords1 # are the newvals in this list?
    if (sum(truthvek)==length(newvals)){ # need them all to be true
      v_selected[[selector]] = newvals   # ok, then overwrite
    }
  }
  observeEvent(input$words_by_letter,{ 
    overwriteIfConsistent(input$letter,input$words_by_letter,words)
  })
}
shinyApp(ui = ui, server = server)

对于它的价值,这就是应用程序的样子:

在此处输入图像描述

于 2017-03-21T22:31:59.273 回答