我有一个闪亮的应用程序,它有多个selectInput
,需要动态更新。下面的R代码显示了重现我的问题的最小例子。
有两个selectInput和一个按钮。 A1
的默认值为A
,B1
的默认值为B
。当我点击按钮时,我会将A
更新为A2
,将B
更新为B4
。但是,B
在第一次点击时变为B3
(错误的结果),但在第二次点击时变为B4
(正确的结果)。
这真是奇怪的行为。我怎么能解决这个问题?谢谢你的任何建议。
PS:我在github上安装了最新版本的闪亮。
三个阶段的屏幕截图(初始,第一次点击,第二次点击)。
重现问题的示例代码。
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)
答案 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
已更新为选项B3
和B4
,自您选择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')
})
现在,这两个选项都有效,最终会得到A2
和B4
。由于sel1
之前已设置为A2
,因此input$sel1
没有变化,这就是第二个观察者不会触发此次的原因。
您可以通过向服务器添加observe({print(input$sel2)})
来确认这一点。这给出了输出
NULL
[1] "B1"
NULL
[1] "B3"
[1] "B4"
现在我有时间想一个解决方案。从我上面所写的内容来看,很明显它不能像你编写代码一样工作。这是因为每当您尝试在同一观察者中设置sel1
和sel2
时,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;