R Shiny-在Shiny模块内插入动态UI

时间:2019-06-01 13:18:22

标签: r shiny

下面的应用程序包含一个模块,该模块在每次单击Add按钮时插入一个UI对象。 UI对象包含两个输入:

  1. 输入1是具有选项selectInputA的{​​{1}}。
  2. 如果用户选择B,则输入2是textInput,而输入2是 A(如果他们选择numericInput

但是,当我单击B时,插入的UI仅包含输入1(Add)-未呈现输入2,如下所示:

enter image description here

所需的输出如下所示:

enter image description here

我不确定这是否是命名空间问题或模块的作用域是否存在问题。将ID打印到控制台将签出:

enter image description here

该应用程序如下:

selectInput

我尝试将模块分为内部和外部模块。内部mod创建输入1和Input 2,外部mod使用library(shiny) # module UI function modUI <- function(id){ ns <- NS(id) tagList( actionButton(ns('add'), 'Add'), div(id = ns('placeholder')) ) } # module server function modServer <- function(input, output, session) { ns = session$ns ctn <- reactiveVal(0) Id <- reactive({ function(id){ ns(paste0(id, ctn())) } }) observeEvent(input$add, { ctn(ctn() + 1) insertUI( selector = paste0('#', ns('placeholder')), ui = div( id = Id()('div'), selectInput(Id()('letter'), 'Letter:', LETTERS[1:2]), uiOutput(Id()('input')) ) ) }) observeEvent(ctn(), { id <- Id()('input') selection <- Id()('letter') print(list(id = id, selection = selection)) req(input[[selection]]) output[[id]] <- renderUI({ req(input[[selection]]) switch( input[[selection]], 'A' = textInput(Id()('text'), 'ENTER TEXT', ''), 'B' = numericInput(Id()('numeric'), 'ENTER NUMBER', '') ) }) }, ignoreInit = TRUE) } # main ui ui <- fluidPage( modUI('mod1') ) # main server server <- function(input, output, session) { callModule(modServer, "mod1") } # run app shinyApp(ui, server) 将它们插入到主应用程序中。不过,这给了我与以前相同的结果。可以在下面查看此代码:

insertUI

我还尝试将library(shiny) # INNER MOD --------------------------------------------------------------- innermodUI <- function(id) { ns = NS(id) tagList( selectInput(ns('letter'), 'Letter:', LETTERS[1:2]), uiOutput(ns('names')) ) } innermodServer <- function(input, output, session) { ns = session$ns output$names <- renderUI({ selection = req(input$letter) switch( selection, 'A' = textInput(ns('text'), 'ENTER TEXT', ''), 'B' = numericInput(ns('numeric'), 'ENTER NUMBER', '') ) }) } # OUTER MOD --------------------------------------------------------------- modUI <- function(id){ ns <- NS(id) tagList( actionButton(ns('add'), 'Add'), div(id = ns('placeholder')) ) } modServer <- function(input, output, session) { ns = session$ns ctn <- reactiveVal(0) Id <- reactive({ function(id){ ns(paste0(id, ctn())) } }) observeEvent(input$add, { ctn(ctn() + 1) filterId = Id()('filter') insertUI( selector = paste0('#', ns('placeholder')), ui = innermodUI(filterId) ) callModule(innermodServer, filterId) }) } # MAIN -------------------------------------------------------------------- ui <- fluidPage( modUI('mod1') ) server <- function(input, output, session) { callModule(modServer, "mod1") } shinyApp(ui, server)包装在renderUI中无济于事。我真的很感谢任何帮助,因为我不熟悉Shiny模块,也不知道下一步该怎么做。

1 个答案:

答案 0 :(得分:1)

我已经设法通过多次尝试错误使它正常工作。据我了解(我仍然是Shiny模块中的新手),您只需要对服务器中创建的输入使用session$ns

library(shiny)

# module UI function
modUI <- function(id){

  ns <- NS(id)

  tagList(
    actionButton(ns('add'), 'Add'),
    div(id = ns('placeholder'))
  )
}

# module server function
modServer <- function(input, output, session) {

  ns = session$ns

  ctn <- reactiveVal(0)

  Id <- reactive({
    function(id){
      paste0(id, ctn())
    }
  })
  IdNS <- reactive({
    function(id){
      ns(paste0(id, ctn()))
    }
  })

  observeEvent(input$add, {

    ctn(ctn() + 1)

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

  observeEvent(ctn(), {

    id <- Id()('input')
    selection <- Id()('letter')

    output[[id]] <- renderUI({

      switch(
        input[[selection]],
        'A' = textInput(IdNS()('text'), 'ENTER TEXT', ''),
        'B' = numericInput(IdNS()('numeric'), 'ENTER NUMBER', '') 
      )

    })

  }, ignoreInit = TRUE)
}

# main ui
ui <- fluidPage(
  modUI('mod1')
)

# main server
server <- function(input, output, session) {
  callModule(modServer, "mod1")
}

# run app
shinyApp(ui, server)