无法在第一次同时更新闪亮的多个选择输入

时间:2016-03-07 12:08:43

标签: r shiny

我有一个闪亮的应用程序,它有多个selectInput,需要动态更新。下面的R代码显示了重现我的问题的最小例子。

有两个selectInput和一个按钮。 A1的默认值为AB1的默认值为B。当我点击按钮时,我会将A更新为A2,将B更新为B4。但是,B在第一次点击时变为B3(错误的结果),但在第二次点击时变为B4(正确的结果)。

这真是奇怪的行为。我怎么能解决这个问题?谢谢你的任何建议。

PS:我在github上安装了最新版本的闪亮。

三个阶段的屏幕截图(初始,第一次点击,第二次点击)。

enter image description here

重现问题的示例代码。

library(shiny)
df <- data.frame(
    A = c('A1', 'A1', 'A2',  'A2'),
    B = c('B1', 'B2', 'B3', 'B4'),
    stringsAsFactors = FALSE
)


# Shiny UI
ui <- fluidPage(
    selectInput('sel1', 'A', choices = NULL, 
                  selected = NULL, 
                  selectize = FALSE)
    , selectInput('sel2', 'B', choices = NULL, 
                  selected = NULL, 
                  selectize = FALSE)
    , actionButton('clickme',  'Click me')
    )

server <- function(input, output, session) {
    observe({
        df_a <- unique(df$A)
        updateSelectInput(session, 'sel1', choices = df_a, selected = NULL)
    })
    observe({
        req(input$sel1)
        df_b <- df[df$A == input$sel1,]
        df_b <- unique(df_b$B)
        updateSelectInput(session, 'sel2', choices = df_b, selected = NULL)
    })
    observe({
        req(input$clickme)
        updateSelectInput(session, 'sel1', selected = 'A2')

        updateSelectInput(session, 'sel2', selected = 'B4')
    })
}

shinyApp(ui, server)

1 个答案:

答案 0 :(得分:1)

这就是为什么你的代码有这种特殊行为的原因:让我们看看你点击按钮后发生的事情。

第一:

# Status: 
# sel1 : choices : "A1", "A2", selected : "A1"
# sel2 : choices : "B1", "B2", selected : "B1"
observe({
  req(input$clickme)
  updateSelectInput(session, 'sel1', selected = 'A2')

  updateSelectInput(session, 'sel2', selected = 'B4')
})

您设法将sel1设置为A2。但目前,sel2没有选择B4,因此设置为NULL

其次,由于input$sel1已更新,因此会触发:

# Status: 
# sel1 : choices : "A1", "A2", selected : "A2"
# sel2 : choices : "B1", "B2", selected : NULL
observe({
  req(input$sel1)
  df_b <- df[df$A == input$sel1,]
  df_b <- unique(df_b$B)

  updateSelectInput(session, 'sel2', choices = df_b, selected = NULL)
})

现在,sel2已更新为选项B3B4,自您选择NULL后,它会自动选择第一个值B3

以下是您再次单击该按钮后会发生的情况。正如所料,这引发了火灾:

# Status: 
# sel1 : choices : "A1", "A2", selected : "A2"
# sel2 : choices : "B3", "B4", selected : "B3"
observe({
  req(input$clickme)
  updateSelectInput(session, 'sel1', selected = 'A2')

  updateSelectInput(session, 'sel2', selected = 'B4')
})

现在,这两个选项都有效,最终会得到A2B4。由于sel1之前已设置为A2,因此input$sel1没有变化,这就是第二个观察者不会触发此次的原因。

您可以通过向服务器添加observe({print(input$sel2)})来确认这一点。这给出了输出

NULL
[1] "B1"
NULL
[1] "B3"
[1] "B4"

修改

现在我有时间想一个解决方案。从我上面所写的内容来看,很明显它不能像你编写代码一样工作。这是因为每当您尝试在同一观察者中设置sel1sel2时,sel2将在之后重置(如果sel1更改)。您需要某种时间表:1)设置sel1然后2)(可能)更新sel2然后3)设置sel2

以下是解决方案,它可以延迟&#34;像我建议的那样设置sel2。然而,它可能不是最漂亮的解决方案,但这取决于问题的扭曲性质。它主要在更新sel2之前检查sel2的设定值。根据是否会更新library(shiny) df <- data.frame( A = c('A1', 'A1', 'A2', 'A2'), B = c('B1', 'B2', 'B3', 'B4'), stringsAsFactors = FALSE ) # Shiny UI ui <- fluidPage( selectInput('sel1', 'A', choices = NULL, selected = NULL, selectize = FALSE) , selectInput('sel2', 'B', choices = NULL, selected = NULL, selectize = FALSE) , actionButton('clickme', 'Click me') ) server <- function(input, output, session) { choice <- NULL observe({ df_a <- unique(df$A) updateSelectInput(session, 'sel1', choices = df_a, selected = NULL) }) observe({ req(input$sel1) df_b <- df[df$A == input$sel1,] df_b <- unique(df_b$B) updateSelectInput(session, 'sel2', choices = df_b, selected = choice) choice <<- NULL }) observe({ req(input$clickme) updateSelectInput(session, 'sel1', selected = 'A2') choice <<- "B4" # build the set of current sel2-choices df_b <- df[df$A == isolate(input$sel1),] df_b <- unique(df_b$B) if(choice %in% df_b){ updateSelectInput(session, 'sel2', choices = df_b, selected = choice) } }) } shinyApp(ui, server) ,它会立即应用更改或将其留给`sel2 - 更新。

select Author_ID
from (select ba.*, count(*) over (partition by Author_ID) as numBooks,
             count(*) over (partition by Book_ID) as numAuthors
      from BookAuthors ba
     ) ba
where numBooks = 1 and numAuthors = 1;