我遇到嵌套selectizeInputs的麻烦,即一组选择输入,其中第一个选择决定第二个选择,控制第三个选择,依此类推。
假设我有一个select1可以让你选择一个数据集,而select2可以让你在数据集中选择一个变量。显然,select2中的选项取决于select1中的选择。我发现如果用户从select2中选择一个变量,然后更改select1,它就不会立即从select2中删除该值,而是通过select1中的新值和旧值进行反应序列。来自select2,它突然引用不同数据集中的变量,这是一个问题。
示例:
library(shiny)
ui =fluidPage(
selectizeInput('d',choices=c('mtcars','iris'),
label="Datasets"),
uiOutput("vars"),
htmlOutput("out")
)
server = function(input, output, session) {
output$vars <- renderUI({
req(input$d)
selectizeInput("v",choices=names(get(input$d)), label="Variables",
options=list(onInitialize=I('function() {this.setValue("");}')))
})
output$out <- renderUI({
req(input$d,input$v)
HTML(paste0("The max is ",max(get(input$d)[[input$v]])))
})
}
runApp(list(ui = ui, server = server))
启动时,选择mpg,并显示最大值。
现在,在选择了mpg之后,如果你切换到虹膜,你将得到一个几乎没有明显的错误,然后它会纠正自己。这是一个玩具示例,因此错误无关紧要,但很容易出现错误更严重的情况(就像我正在开发的应用程序一样)。
有没有办法处理嵌套的selectizeInputs,以便上游selectizeInput中的更改在更改时不会使用旧值的下游选择性输入进行评估?
由于
编辑:这个问题对模块的影响比我认为的更多:
library(shiny)
library(DT)
testModUI <- function(id) {
ns <- NS(id)
DT::dataTableOutput(ns("out"))
}
testMod <- function(input, output, session, data) {
output$out <- DT::renderDataTable({
data()
},caption="IN MODULE")
}
ui =fluidPage(
selectizeInput('d',choices=c('mtcars','iris'),
label="Datasets"),
uiOutput("vars"),
testModUI("test"),
DT::dataTableOutput("test2")
)
server = function(input, output, session) {
output$vars <- renderUI({
req(input$d)
selectizeInput("v",choices=names(get(input$d)), label="Variables",
options=list(onInitialize=I('function() {this.setValue("");}')))
})
observe({
req(input$d,input$v)#,get(input$d)[[input$v]])
validate(
need(input$v %in% names(get(input$d)), 'Wait.')
)
callModule(testMod,"test",reactive(data.frame(v1=max(get(input$d)[[input$v]]))))
})
output$test2 <- DT::renderDataTable({
req(input$d,input$v)#,get(input$d)[[input$v]])
validate(
need(input$v %in% names(get(input$d)), 'Wait.')
)
data.frame(v1=max(get(input$d)[[input$v]]))
},caption="OUTSIDE MODULE")
}
runApp(list(ui = ui, server = server))
答案 0 :(得分:1)
您好,您可以设置条件来检查您的代码是否会运行,在这里您只需要input$v
成为input$d
的有效变量,所以:
output$out <- renderUI({
req(input$d,input$v)
if (input$v %in% names(get(input$d))) {
HTML(paste0("The max is ",max(get(input$d)[[input$v]])))
}
})
# or
output$out <- renderUI({
req(input$d,input$v)
validate(
need(input$v %in% names(get(input$d)), 'Wait.')
)
HTML(paste0("The max is ",max(get(input$d)[[input$v]])))
})
使用模块编辑,您可以使用表达式定义模块以进行验证,如下所示:
testMod <- function(input, output, session, data, validExpr) {
output$out <- DT::renderDataTable({
validate(need(validExpr(), FALSE))
data()
},caption="IN MODULE")
}
使用函数中的表达式调用服务器中的模块:
observe({
req(input$d,input$v)
callModule(
module = testMod,
id = "test",
data = reactive({ data.frame(v1=max(get(input$d)[[input$v]])) }),
validExpr = function() input$v %in% names(get(input$d))
)
})