英文:
initiate observeEvent() inside a module using an external button (or other trigger)
问题
我已经查看了关于observeEvent()、updateSelectInput()和模块通信的所有帖子,但仍然找不到答案。我错过了什么?
我想能够使用单个按钮重置多个用户输入部件。每个用户输入部件都是其自己的模块。我使用模块来处理用户输入,因为我有一个包含多个数据表的大型应用程序,每个数据表都需要不同的筛选器来接受用户输入。我不想为每个输入部件包含重置按钮,因为它们太多了,会使应用程序显得非常拥挤。我希望能够只使用基本的library(shiny)来实现这一点,而不是添加更多的额外包。shiny.js据说可以更容易地实现这一点,但我也无法使其正常工作,而且真的看起来不应该必须这样做。
这是一个简单的可复制示例:
library(shiny)
# 我正在使用的筛选器模块的简化版本 - 关键是我需要能够使用单个按钮来更新多个筛选器模块
selectinput_UI <- function(id) {
ns <- NS(id)
tagList(
selectInput(inputId = ns("select_input"),
label = "Input",
choices = c("choice1", "choice2", "choice3", "choice4"),
selected = "choice2"),
verbatimTextOutput(outputId = ns("user_output")),
verbatimTextOutput(outputId = ns("button_clicks")) # 证明按钮实际上是在模块内部点击的
)
}
# 筛选器模块的服务器端 - 包括外部按钮的响应值输入
selectinput_server <- function(id, reset) {
moduleServer(
id,
function(input, output, session) {
ns <- session$ns
output$user_output <- renderText({input$select_input})
output$button_clicks <- renderText({reset()})
# observeEvent应该在事件表达式更改时触发任何时候
observeEvent(reset(), {
updateSelectInput(session = session,
inputId = ns("select_input"),
selected = "choice3")
})
}
)
}
ui <- fluidPage(
selectinput_UI(id = "test"),
actionButton(inputId = "button",
label = "Reset")
)
server <- function (input, output, session) {
click <- reactive({input$button})
selectinput_server(id = "test", reset = click)
}
shinyApp(ui = ui, server = server)
我尝试了许多方法,我提供的简单示例可能是我认为最有希望的,但它仍然无法正常工作,我不明白为什么。它没有抛出任何错误,按钮点击,selectInput()似乎工作正常,但当单击按钮时,值不会像应该的那样更新。我在updateSelectInput()中做错了什么吗?有什么想法?想法?我是否漏掉了一些明显的东西?
同时,我也愿意听取其他关于如何实现我的最终目标的想法,即使用单个按钮重置一系列各自为一模块的筛选器。
其他遇到类似问题的人缺少服务器端的ns(),但显然这不是我的问题。
这是我见过的与我尝试做的最接近的东西:https://stackoverflow.com/questions/53492482/modularizing-r-shiny-code-observeevent-function-in-module 但仍然没有改变什么。
英文:
I have reviewed every post I can find about observeEvent(), updateSelectInput(), and module communication, and have yet to find an answer. What am I missing?
I want to be able to reset multiple user input widgets using a single button. Each user input widget is its own module. I'm using modules for the user inputs because I have a large app with multiple data tables that each need different filters that take user input. I do NOT want to include a reset button for each input widget because there are too many of them and it would crowd the app way too much. I want to be able to do this with just the basic library(shiny), not by adding even more extra packages. shiny.js supposedly has a way to do this more easily but I couldn't get that to work either, and it really seems like it shouldn't be necessary.
Here is a simple, reproducible example:
library(shiny)
#simple version of a filter module I'm using - the point is that I need to be able to use a single button to update multiple filter modules
selectinput_UI <- function(id) {
ns <- NS(id)
tagList(
selectInput(inputId = ns("select_input"),
label = "Input",
choices = c("choice1", "choice2", "choice3", "choice4"),
selected = "choice2"),
verbatimTextOutput(outputId = ns("user_output")),
verbatimTextOutput(outputId = ns("button_clicks")) #demonstrates that the button is, in fact, clicking, even within the module)
)
}
#server-side for the filter module - includes an input for the reactive value of the outer button
selectinput_server <- function(id, reset) {
moduleServer(
id,
function(input, output, session) {
ns <- session$ns
output$user_output <- renderText({input$select_input})
output$button_clicks <- renderText({reset()})
#observeEvent SHOULD trigger any time the eventExpr changes
observeEvent(reset(), {
updateSelectInput(session = session,
inputId = ns("select_input"),
selected = "choice3")
})
}
)
}
ui <- fluidPage(
selectinput_UI(id = "test"),
actionButton(inputId = "button",
label = "Reset")
)
server <- function (input, output, session) {
click <- reactive({input$button})
selectinput_server(id = "test", reset = click)
}
shinyApp(ui = ui, server = server)
I've tried many approaches, the simple example I've provided is the most promising I think, but it still doesn't work, and I don't understand why. It doesn't throw any errors, the button clicks, selectInput() seems to work fine, but the value does not update like it should when the button is clicked. Is something wrong with how I've done the updateSelectInput()? Ideas? Thoughts? Am I missing something obvious?
Also open to other ideas about how to approach my end goal of having a single button that resets a series of individual filters that are each their own module.
Others with similar types of issues are lacking the ns() on the server-side, but that's clearly not my problem here.
This is the closest thing I've seen to what I'm trying to do: https://stackoverflow.com/questions/53492482/modularizing-r-shiny-code-observeevent-function-in-module
But still doesn't change anything.
答案1
得分: 0
你差一点就到了。你多次调用了 ns
。将 updateSelectInput
更改为以下内容:
updateSelectInput(
session = session,
inputId = "select_input",
selected = "choice3"
)
因为你已经指定了 session 参数,所以不需要在 inputId 上调用 ns
。
英文:
You were almost there. You have an extra call to ns
. Change the updateSelectInput to this:
updateSelectInput(
session = session,
inputId = "select_input",
selected = "choice3"
)
There's no need to call ns
on the inputId since you have specified the session parameter.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论