【问题标题】:R Shiny - Dynamically adding dependent inputs using insertUIR Shiny - 使用 insertUI 动态添加依赖输入
【发布时间】:2019-10-17 00:02:34
【问题描述】:

下面的应用程序包含一个actionButtonAdd,单击时会插入两个输入。

第一个输入是一个 selectInput,其中有 AB 选项。如果用户选择A,则第二个输入是textInput;如果用户选择B,则输入numericInput。我不确定如何捕获这种依赖关系。

我尝试将一个事件处理程序(下面代码中的第二个observeEvent)附加到每个selectInput,它侦听该selectInput 的值并使用renderUI 相应地呈现第二个输入。但这不起作用。我也对在 observeEvent 中使用渲染函数持谨慎态度,因为我已经读过在观察者中使用渲染不是好的做法(不完全确定为什么)。看起来也很乱。

应用程序:

library(shiny)

  ui <- fluidPage(
    actionButton('add', 'Add'),
    div(id = 'placeholder')
  )

  server <- function(input, output, session) {

    rv = reactiveValues(ctn = NULL)

    observeEvent(input$add, {

      rv$ctn = rv$ctn + 1

      Id = function(id, ctn = rv$ctn) paste0(id, ctn)

      insertUI(
        selector = '#placeholder',
        ui = div(
          id = Id('div'),
          selectInput(Id('letter'), 'Letter:', LETTERS[1:2]),
          uiOutput(Id('input'))
        )
      )

      observeEvent(Id('letter'), {
        output[[Id('input')]] <- renderUI({

          switch(
            input[[Id('letter')]],
            'A' = textInput(Id('text'), '', ''),
            'B' = numericInput(Id('numeric'), '', '')
          )
        })

      })
    })

  }

  shinyApp(ui = ui, server = server)

插入的第一个 UI 块按预期工作 - 两个输入都被渲染。但是,在随后的块中(下面屏幕截图中的块 2 和 3)仅呈现 selectInput。

这是截图:

【问题讨论】:

    标签: r shiny


    【解决方案1】:

    下面是一个工作代码。主要问题是您的ctn 反应值初始化为NULL,因为NULL + 1 = numeric(0)numeric(0) + 1 = numeric(0)

    library(shiny)
    
    ui <- fluidPage(
      actionButton('add', 'Add'),
      div(id = 'placeholder')
    )
    
    server <- function(input, output, session) {
    
      ctn <- reactiveVal(0)
      Id <- reactive({
        function(id){
          paste0(id, ctn())
        }
      })
    
      observeEvent(input$add, {
    
        ctn(ctn() + 1)
    
        insertUI(
          selector = '#placeholder',
          ui = div(
            id = Id()('div'),
            selectInput(Id()('letter'), 'Letter:', LETTERS[1:2]),
            uiOutput(Id()('input'))
          )
        )
    
      })
    
      observeEvent(ctn(), {
        id <- Id()('input')
        selection <- Id()('letter')
        output[[id]] <- renderUI({
          req(input[[Id()('letter')]])
          switch(
            input[[selection]],
            'A' = textInput(Id()('text'), 'ENTER TEXT', ''),
            'B' = numericInput(Id()('numeric'), 'ENTER NUMBER', '')
          )
        })
      }, ignoreInit = TRUE)
    
    }
    

    【讨论】:

    • 感谢您关注@Stéphane。您的代码呈现两个输入,但是当我单击 Add 两次然后将第二个 selectInput 的值从 A 更改为 B 时,两个块中的相关输入都更改为 numericInput,即使我已经离开了第一个selectInput 的值在A 不变。通过将开关更改为switch(input[[Id()('letter')]], 'A' = textInput(Id()('text'), label = 'Text input:', value = 'This is a text input.'), 'B' = numericInput(Id()('numeric'), label = 'Numeric input:', value = 123)),您可以更清楚地看到这一点。
    • @user51462 确实如此。看我的更新。我对observeEvent(ctn() 做了一些更改。
    • 很抱歉再次打扰您@Stéphane,但是当我尝试在模块中使用它时,renderUI 不再起作用。 uiOutput 出现在 DOM 中,但它是空的,你知道为什么吗?我尝试将renderUI 包装在delay() 中,以便它等到selectInput 在触发之前呈现,但它不起作用。我在模块服务器中使用ns = session$ns 并将Id() 反应式修改为ns(paste0(id, ctn()))
    • 我不确定这方面的礼仪是什么,但如果您愿意,我可以发布一个新问题。
    • @user51462 是的,请发布一个新问题。我不精通 Shiny 模块,所以我不能保证我会提供帮助。
    猜你喜欢
    • 2018-02-28
    • 1970-01-01
    • 2018-11-28
    • 1970-01-01
    • 2013-10-28
    • 1970-01-01
    • 2019-02-05
    • 2017-05-31
    • 2021-11-11
    相关资源
    最近更新 更多