【问题标题】:Is there a way to make a wrapper function for renderUI in Shiny (R)?有没有办法在 Shiny (R) 中为 renderUI 制作包装函数?
【发布时间】:2022-01-26 04:30:45
【问题描述】:

我需要使用renderUI 根据另一个输入值创建多个输入选项。我想将renderUI 中的所有内容作为一个函数包装起来,这样我就可以将其应用于许多类似的输入。这是一个简化的示例(对我有用,但我不想多次重复 renderUI 部分,因为我还有很多其他输入,例如 i1):

library(shiny)
ui <- fluidPage(
    fluidRow(
        selectInput(
            inputId = 'i1',
            label = 'choice 1',
            choices = list(5, 10)
        ),
        uiOutput('o1')
    )
)
server <- function(input, output, session) {
    output$o1 <- renderUI(
        fluidRow(
            sliderInput(
                inputId = 's1',
                label = 'slider 1',
                min = 0, max = as.numeric(input$i1) * 10,
                value = 0.5
            ),
            sliderInput(
                inputId = 's2',
                label = 'slider 2',
                min = 0, max = as.numeric(input$i1) * 100,
                value = 0.5
            )
        )
    )
}
shinyApp(ui = ui, server = server)

问题是,当我尝试将其包装到函数中时,renderUI 创建的输出在我更改输入值时停止更新。这是对我不起作用的代码:

library(shiny)
renderUI_warpper <- function(i){
    renderUI(
        fluidRow(
            sliderInput(
                inputId = 's1',
                label = 'slider 1',
                min = 0, max = as.numeric(i) * 10,
                value = 0.5
            ),
            sliderInput(
                inputId = 's2',
                label = 'slider 2',
                min = 0, max = as.numeric(i) * 100,
                value = 0.5
            )
        )
    )
}
ui <- fluidPage(
    fluidRow(
        selectInput(
            inputId = 'i1',
            label = 'choice 1',
            choices = list(5, 10)
        ),
        uiOutput('o1')
    )
)
server <- function(input, output, session) {
    output$o1 <- renderUI_warpper(input$i1)
}
shinyApp(ui = ui, server = server)

【问题讨论】:

    标签: r shiny renderui


    【解决方案1】:

    虽然我看不出这样做有什么意义,因为即使您将该部分移到一个函数中,您仍然必须定义每个 sliderInput,这是一种方法。

    重点是您应该包装 Input 而不是 renderUI,因为您需要反应式表达式才能更新输入,而反应式只能在另一个反应式或 render* 函数中使用

    library(shiny)
    
    ui <- fluidPage(
      fluidRow(
        selectInput(
          inputId = 'i1',
          label = 'choice 1',
          choices = list(5, 10)
        ),
        uiOutput('o1')
      )
    )
    server <- function(input, output, session) {
      wrapper <- reactive({
        function(i){
          fluidRow(
            sliderInput(
              inputId = 's1',
              label = 'slider 1',
              min = 0, max = as.numeric(i) * 10,
              value = 0.5
            ),
            sliderInput(
              inputId = 's2',
              label = 'slider 2',
              min = 0, max = as.numeric(i) * 100,
              value = 0.5
            )
          )
          }
      })
      output$o1 <- renderUI(wrapper()(input$i1))
    }
    shinyApp(ui = ui, server = server)
    

    【讨论】:

    • 您可以在服务器外部声明该函数,然后以input$i1 作为参数调用它。 create_sliders &lt;- function(i){ fluidRow( sliderInput( inputId = 's1', label = 'slider 1', min = 0, max = as.numeric(i) * 10, value = 0.5 ), sliderInput( inputId = 's2', label = 'slider 2', min = 0, max = as.numeric(i) * 100, value = 0.5 ) ) }
    • 服务器内部:output$o1 &lt;- renderUI({ create_sliders(input$i1) })
    • @jpdugo17 恐怕相当于OP的提议,当selectInput改变时不会更新比例,因为create_sliders周围没有reactive@
    • 这对我有用,我喜欢这个想法:使 warpper 成为服务器内部的反应函数。现在我想知道为什么@jpdugo17 的方法也对我有用。基于@englealuze' cmets 它不应该工作......
    • @coffee 刚刚对此进行了测试。它确实有效。我猜renderUI({ }) 的工作是为create_sliders 等普通函数添加一些反应特性@
    【解决方案2】:

    这是一个可能的替代方案:

    library(shiny)
    
    create_sliders <- function(i) {
      fluidRow(
        column(
          width = 12,
          sliderInput(
            inputId = "s1",
            label = "slider 1",
            min = 0, max = as.numeric(i) * 10,
            value = 0.5
          ),
          sliderInput(
            inputId = "s2",
            label = "slider 2",
            min = 0, max = as.numeric(i) * 100,
            value = 0.5
          )
        )
      )
    }
    
    ui <- fluidPage(
      fluidRow(
        selectInput(
          inputId = "i1",
          label = "choice 1",
          choices = list(5, 10)
        ),
        uiOutput("o1")
      )
    )
    server <- function(input, output, session) {
      output$o1 <- renderUI({
        create_sliders(input$i1)
      })
    }
    shinyApp(ui = ui, server = server)
    

    【讨论】:

    • 太好了,谢谢。这确实对我有用。我通过将 renderUI 移出更改了函数,并且每次更改输入或函数的反应值更改时都会更新。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-24
    • 2020-07-31
    • 2011-10-01
    • 1970-01-01
    • 2019-08-01
    • 2020-02-12
    • 2015-04-15
    相关资源
    最近更新 更多