使用insertUI和模块动态添加选项卡

时间:2019-09-03 17:42:08

标签: r shiny

我正在尝试创建一个标签集,在其中动态添加标签。每个新标签页都带有带有图像的相同轮播。轮播是从模块加载的。

这将是理想的最终结果,但适用于多个动态添加的标签页: End result

阅读其他SO问题使我相信我可能需要一个嵌套模块。另外,我在insertUI上犯了一个错误。帮助非常感谢!

这是一个MVE,您需要在其中将一个png放置在与代码相同的文件夹中:

library(shiny)
library(slickR)

my_module_UI <- function(id) {
  ns <- NS(id)
  slickROutput(ns("slickr"), width="100%")
}

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

  output$slickr <- renderSlickR({
    imgs <- list.files("", pattern=".png", full.names = TRUE)
    slickR(imgs)
  })
}

ui <- fluidPage(  
  tabItem(tabName = "main_tab_id",
          tabsetPanel(id = "test_tabs",
                      tabPanel(
                        title = "First tab",
                        value = "page1",
                        fluidRow(textInput('new_tab_name', 'New tab name'),
                                 actionButton('add_tab_button','Add'))
                      )
          )
  )
)

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

  tab_list <- NULL

  observeEvent(input$add_tab_button,
               {
                 tab_title <- input$new_tab_name

                 if(tab_title %in% tab_list == FALSE){

                   appendTab(inputId = "test_tabs",
                             tabPanel(
                               title=tab_title,
                               div(id="placeholder") # Content
                             )
                   )

                   # A "unique" id based on the system time
                   new_id <- gsub("\\.", "", format(Sys.time(), "%H%M%OS3"))
                   insertUI(
                     selector = "#placeholder",
                     where = "beforeBegin",
                     ui = my_module_UI(new_id)
                   )

                   callModule(my_module, new_id)

                   tab_list <<- c(tab_list, tab_title)

                 }
                 updateTabsetPanel(session, "test_tabs", selected = tab_title)
               })
}

shinyApp(ui, server)

1 个答案:

答案 0 :(得分:1)

这是一个有趣的模块练习。

  1. carousel_module只是渲染轮播
  2. my_tab模块,为每个选项卡创建一个选项卡和一个observeEvent,用于监听选项卡的点击
library(shiny)
library(slickR)

carousel_ui <- function(id){
  ns <- NS(id)
  slickROutput(ns("slickr"), width="100%")
}

carousel_module <- function(input, output, session) {
  output$slickr <- renderSlickR({
    imgs <- list.files("~/Desktop/imgs", pattern=".png", full.names = TRUE)
    slickR(imgs)
  })
}

my_tab <- function(input,output,session,parent_session,tab_element,tab_name){

  ns = session$ns

  appendTab(inputId = "test_tabs",
            tabPanel(
              title = tab_name,
              value = tab_name,
              carousel_ui(ns("carousel")) # Operating in the parent session so explicitly supply the namespace
          ),
          session = parent_session
  )

  updateTabsetPanel(parent_session, "test_tabs", selected = tab_name) # Refer to test_tabs from the parent namespace

  # Need to update the carousel every time the user clicks on a tab
  # Else the carousel is only updated on the latest tab created

  observeEvent(tab_element(),{
    req(tab_element())

    if(tab_element() == tab_name){
      cat("Running\n")
      callModule(carousel_module,"carousel")# This module knows the namespace so no need to supply the namespace
    }
  })

}

ui <- fluidPage(  
      tabsetPanel(id = "test_tabs",
                  tabPanel(
                    title = "First tab",
                    value = "page1",
                    fluidRow(textInput('new_tab_name', 'New tab name'),
                             actionButton('add_tab_button','Add'))
                  )
      )
  )
)

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

  tab_list <- NULL

  observeEvent(input$add_tab_button,{

                 tab_title <- input$new_tab_name
                 callModule(my_tab,tab_title,session,reactive(input$test_tabs),input$new_tab_name)

               })
}

shinyApp(ui, server)