Dynamically adding modules in shiny

后端 未结 4 1568
春和景丽
春和景丽 2021-01-06 13:17

This isn\'t about creating modules using renderUI. With renderUI as i understand it you put a placeholder inside the UI function and then you write your controls/widget insi

4条回答
  •  猫巷女王i
    2021-01-06 13:59

    Another answer that extends, what MySchizoBuddy has been doing. It might also not be fully satisfying, but it works.

    I added a script, that simply moves all Elements from the dynamic creator to a target div. That way, dynamically creating elements does not erase those created before.

    #Dynamically adding modules
    library(shiny)
    
    #slider module ------------------------
    sliderUI <- function(id) {
      ns <- NS(id)
      tagList(
        sliderInput(ns("bins"), "Number of Bins:", min = 1, max = 5, value = 3),
        textOutput(ns("textBins"))  
      )
    }
    
    slider <- function(input, output, session) {
      output$textBins <- renderText({
        input$bins
      })
    }
    
    
    #shiny app ------------------------
    ui <- fixedPage(
      fixedRow(
        column(width = 4, wellPanel(
          h4("Slider Module"),
          sliderUI("originalSlider"),
          actionButton("addSliderModule", "Add Slider Module"))
        ),
        column(width = 4, wellPanel(
          h4("Dynamic Loading Modules"),
          p("Clicking on the 'Add' button on the left should add the module here. You should be able to duplicate that slider module as many times as the button is clicked"),
          hr(),
          tags$script(HTML('
            Shiny.addCustomMessageHandler("moveModule", function(message) {
              var source = document.getElementById("addModule").childNodes;
              var target = document.getElementById("target");
              for (var i = 0; i < source.length; i++) {
                target.appendChild(source[i]);
              }
            })
          ')),
          tags$div(id = "target"),
          uiOutput("addModule"))
        )
      )
    )
    
    server <- function(input, output, session) {
      #server code for the original module
      callModule(slider, "originalSlider")
    
      #Here we add the UI and callModule of the duplicate module
      observeEvent(input$addSliderModule, {
    
        session$sendCustomMessage(type = "moveModule", message = "Something")
    
        duplicateSliderid <- paste0("duplicateSlider", input$addSliderModule)
    
        output$addModule <- renderUI({
          sliderUI(duplicateSliderid)
        })
        callModule(slider, duplicateSliderid)
      })
    }
    
    shinyApp(ui, server)
    

提交回复
热议问题