2016-09-26 69 views
1

我想在一个页面上有一个相同的actionButton()的可变数目,它们都由一个observeEvent()函数处理。带有一个事件处理程序的多个操作按钮闪亮?

例如,在一个表的变长表中,我希望每个内部表都有一个链接到该表的更多信息的按钮。

<form ...> 
    <input id="table_number" type="hidden" value="1"/> 
    <input type="submit" value="Examine"/> 
</form> 

当按下一个按钮,你可以检查隐藏:

在标准的HTML,你用一个简单的表格,在您使用一个隐藏的输入指定内部表号,这样做输入以查看它是哪一个。

有没有办法在Shiny中做到这一点?我想出的唯一解决方案是给每个actionButton()它自己的inputId。这需要为每个按钮分别指定一个observeEvent()。必须提前创建这些按钮,并设置最大数量的按钮。

+0

还有一个闪亮的submitButton也是http://shiny.rstudio。com/gallery/submitbutton-demo.html –

+0

@PorkChop - 感谢您的链接。我已经忘记了这一个。但不幸的是,'submitButton'捕获整个页面上的所有事件,直到您点击它。在标准HTML中,它只会是该按钮的'

'中的事件,并且您可以在页面上拥有多个表单。我意识到我正在寻找的仅仅是一个“actionButton”,它的值字段可以在按钮被创建时分配,并在按下按钮时返回。相反,'actionButton'返回被点击的次数。 – 3D0G

+0

您可以将所有按钮绑定到一个事件,使用'eventReactive'或'observeEvent'注意,这些事件可以包含多个由逗号分隔的事件。 http://shiny.rstudio.com/reference/shiny/latest/observeEvent.html –

回答

2

您可以使用闪亮的模块:您可以拥有相同的可变数字actionButton。这些在ab_moduleUI部分中定义。他们由他们自己的observeEvent处理,但它只能在ab_module部分中定义一次。

使用lapply可以创建任意数量的actionButton

编辑:您不必事先指定按钮的数量:使用renderUI在服务器端生成UI元素。

为了演示目的,我添加了一个numericInput来增加/减少要渲染的模块数量。

# UI part of the module 
ab_moduleUI <- function(id){ 
    ns <- NS(id) 
    tagList(
    fluidRow(
     actionButton(ns("btn"), paste("ActionButton", id, sep="-")), 
     textOutput(ns("txt")) 
    ) 
) 
} 

# Server part of the module 
ab_module <- function(input, output, session){ 
    observeEvent(input$btn,{ 
    output$txt <- renderText("More information shown") 
    }) 
} 


# UI 
ui <- fluidPage(
    # lapply(paste0("mod", 1:no_btn), ab_moduleUI) 
    numericInput("num", "Number of buttons to show" ,value = 5, min = 3, max = 10), 
    uiOutput("ui") 
) 

# Server side 
server <- function(input, output, session){ 
    observeEvent(input$num, { 
    output$ui <- renderUI({ 
     lapply(paste0("mod", 1:input$num), ab_moduleUI) 
    }) 

    lapply(paste0("mod", 1:input$num), function(x) callModule(ab_module, x)) 
    }) 

} 

shinyApp(ui, server) 

了解更多关于光泽模块here

+0

GdY - 谢谢你。我之前没有使用过模块,并且会更深入地研究它。但在第一眼看来,这似乎是我已经做的很多 - 给每个按钮自己的ID,然后使用他们的唯一ID来找出哪个按钮被按下。这是行得通的,但是当你运行Shiny时,你必须指定最大数量的按钮('no_btn'),而我不知道我需要的最大数量,直到用户加载一些数据(从PubMed/Embase下载的引文/ Cochrane等,就我而言)。标准的HTML很容易处理,我以为我错过了一些东西。 – 3D0G

+0

刚编辑答案。我认为这是你正在寻找的。 – GyD

+0

是的。在阅读你建议的信息之后,我认为你是对的 - 命名空间冲突(具有相同ID的多个对象)似乎是问题,模块似乎是答案。感谢您花费在此上的时间! – 3D0G

0

关于使用闪亮的模块来回答我原来的问题...

我想有一种方法可以有多个按钮一个页面可以由一个observeEvent()来处理,这很容易处理传统的HTML表单,如原始问题所示。

使用Shiny模块的GyD演示代码几乎解决了这个问题,但实际上并没有返回哪个按钮被按到主服务器。我花了很长的时间,但我终于想通了如何编写一个模块,确实让主服务器知道按钮被按下其中:

actionInput <- function(id) { 
    ns <- NS(id) 
    tagList(
     textInput(ns("text"), label=NULL, value=id), 
     actionButton(ns("button"), "OK") 
    ) 
} 

action <- function(input, output, session) { 
    eventReactive(input$button, { 
     return(input$text) 
    }) 
} 

ui <- fluidPage(fluidRow(column(4, actionInput("b1")), 
         column(4, actionInput("b2")), 
         column(4, uiOutput("result")))) 

server <-function(input, output, session) { 
    b1 <- callModule(action, "b1") 
    observeEvent(b1(), { 
     output$result = renderText(b1()) 
    }) 
    b2 <- callModule(action, "b2") 
    observeEvent(b2(), { 
     output$result = renderText(b2()) 
    }) 
} 

shinyApp(ui = ui, server = server) 

(在实际应用中,我会做的textInputs无形的,如他们只是在那里提供一个按钮被按下的ID)

该解决方案仍然需要主服务器中的每个按钮observeEvent()。有可能以某种其他方式使用模块来解决问题,但我一直无法弄清楚。

我原来的选择,在主服务器中为每个按钮使用一个单独的observeEvent(),实际上比这个演示代码的扩展应该是一百个或更多按钮更简单。

相关问题