如何在具有多个选项卡和多个模块的闪亮应用程序中使用 Cicerone 指南?

问题描述 投票:0回答:1

我查看了有关如何将 Cicerone 与模块一起使用以及如何将其与选项卡一起使用的文档。然而,在我将两者结合起来形成一个具有嵌套选项卡和嵌套模块的更复杂应用程序的情况下,我无法创建一个浏览多个选项卡的指南。

当我首先切换到作为游览一部分的第二个选项卡,然后运行游览时,它可以工作,因此我的元素是正确的,但不知何故,它没有切换到打开的选项卡以将元素放入上下文中。 (请注意,此处不包含该功能)

是否有可能当我在第一个选项卡上时,第二个选项卡中的元素尚未创建?如果是这样,我不知道 tab 和 tab_id 参数将如何工作,除非这是由于我的模块和选项卡的分层性质所致。

这是一个简化的示例应用程序:

library(shiny)
library(tidyverse)
library(cicerone)



# Module for subtabs ------------------------------------------------------

mod_subtabs_ui <- function(id){
  ns <- NS(id)
  tagList(
    tabsetPanel(
      id = ns("subTabs"),
      tabPanel("Chart", mod_chart_ui(ns("chart_1"))),
      tabPanel("Table", mod_table_ui(ns("table_1")))
    )
  )
}

mod_subtabs_server <- function(id){
  moduleServer( id, function(input, output, session){
    ns <- session$ns

    mod_chart_server("chart_1")
    mod_table_server("table_1")
  })
}


# Module for chart --------------------------------------------------------

mod_chart_ui <- function(id) {
  ns <- NS(id)

  tagList(
      plotOutput(ns("chart"))
  )
}

mod_chart_server <- function(id) {
  moduleServer( id, function(input, output, session){
    ns <- session$ns

    output$chart <- renderPlot(ggplot(mtcars, aes(x = mpg, y = cyl)) + geom_point())

  })
}


# Module for table --------------------------------------------------------

mod_table_ui <- function(id) {
  ns <- NS(id)

  tagList(
    sidebarLayout(
      sidebarPanel(
        mod_filter_ui(ns("filter_chart"))),
      mainPanel(
        tableOutput(ns("table"))
      )
    )
  )
}

mod_table_server <- function(id) {
  moduleServer( id, function(input, output, session){
    ns <- session$ns

    filt_mtcars <- isolate(mod_filter_server("filter_chart"))

    output$table <- renderTable(filt_mtcars())

  })
}


# Module for filter -------------------------------------------------------

mod_filter_ui <- function(id) {
  ns <- NS(id)
  tagList(
      selectInput(ns("cyl_filt"),
                  label = "Filter for # of Cylinders",
                  choices = NULL)
    )
}

mod_filter_server <- function(id) {
  moduleServer( id, function(input, output, session){
    ns <- session$ns

    updateSelectInput("cyl_filt",
                      session = session,
                      choices = unique(mtcars$cyl),
                      selected = unique(mtcars$cyl)[1])

    filt_mtcars <- reactive(mtcars |> filter(cyl == input$cyl_filt))

    return(filt_mtcars)


  })
}



# Cicerone ----------------------------------------------------------------

guide <- Cicerone$
  new()$
  step(el = "mainTabs",
       "Main Tabs",
       "These are the main tabs set in the main server")$
  step(el = "tab1-subTabs",
       "Sub Tabs",
       "These are the subtabs under Tab1")$
  step(el = "tab1-chart_1-chart",
       "Chart",
       "This is a chart!")$
  step(el = "tab1-table_1-table", #This step does not work
       "Table",
       "This is a table!",
       tab = "table_1",
       tab_id = "tab1-table_1")$
  step(el = "tab1-table_1-table-cyl_filt", #This step does not work
       "Filters",
       "Here you can filter the table by number of cylinders.")




# Main app ----------------------------------------------------------------

ui <- fluidPage(
  use_cicerone(),
  mainPanel(
    tabsetPanel(id = "mainTabs",
      tabPanel("tab1", mod_subtabs_ui("tab1")),
      tabPanel("tab2", mod_subtabs_ui("tab2"))
    )
  )
)

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

  guide$init()$start()
  
  mod_subtabs_server("tab1")
  mod_subtabs_server("tab2")


}

shinyApp(ui = ui, server = server)

r shiny cicerone
1个回答
0
投票

是否有可能当我在第一个选项卡上时, 第二个选项卡尚未创建?如果是这样,我不知道该选项卡如何 和 tab_id 参数将永远有效,除非是由于 我的模块和选项卡的层次结构。

是的,我做了三项主要更改,应该可以使用当前开发版本的

cicerone
(
1.0.5.9000
)。

  • 第四步中的

    tab
    tab_id
    必须更改为

    tab = "Table",
    tab_id = "tab1-subTabs"
    
  • 表格需要 suspendWhenHidden = FALSE:

    outputOptions(output, "tab1-table_1-table", suspendWhenHidden = FALSE)
    
  • 我按类别选择第二个选项卡上的

    selectInput
    ,因为在您的应用程序中它没有
    id
    :

    el = ".form-group.shiny-input-container"
    

enter image description here

library(shiny)
library(tidyverse)
library(cicerone)
#packageVersion("cicerone")
#[1] ‘1.0.5.9000’

# Module for subtabs ------------------------------------------------------

mod_subtabs_ui <- function(id){
  ns <- NS(id)
  tagList(
    tabsetPanel(
      id = ns("subTabs"),
      tabPanel("Chart", mod_chart_ui(ns("chart_1"))),
      tabPanel("Table", mod_table_ui(ns("table_1")))
    )
  )
}

mod_subtabs_server <- function(id){
  moduleServer( id, function(input, output, session){
    ns <- session$ns
    
    mod_chart_server("chart_1")
    mod_table_server("table_1")
  })
}


# Module for chart --------------------------------------------------------

mod_chart_ui <- function(id) {
  ns <- NS(id)
  
  tagList(
    plotOutput(ns("chart"))
  )
}

mod_chart_server <- function(id) {
  moduleServer( id, function(input, output, session){
    ns <- session$ns
    
    output$chart <- renderPlot(ggplot(mtcars, aes(x = mpg, y = cyl)) + geom_point())
    
  })
}


# Module for table --------------------------------------------------------

mod_table_ui <- function(id) {
  ns <- NS(id)
  
  tagList(
    sidebarLayout(
      sidebarPanel(
        mod_filter_ui(ns("filter_chart"))),
      mainPanel(
        tableOutput(ns("table"))
      )
    )
  )
}

mod_table_server <- function(id) {
  moduleServer( id, function(input, output, session){
    ns <- session$ns
    
    filt_mtcars <- mod_filter_server("filter_chart")
    
    output$table <- renderTable(filt_mtcars())
    
  })
}


# Module for filter -------------------------------------------------------

mod_filter_ui <- function(id) {
  ns <- NS(id)
  tagList(
    selectInput(ns("cyl_filt"),
                label = "Filter for # of Cylinders",
                choices = NULL)
  )
}

mod_filter_server <- function(id) {
  moduleServer( id, function(input, output, session){
    ns <- session$ns
    
    updateSelectInput("cyl_filt",
                      session = session,
                      choices = unique(mtcars$cyl),
                      selected = unique(mtcars$cyl)[1])
    
    filt_mtcars <- reactive(mtcars |> filter(cyl == input$cyl_filt))
    
    return(filt_mtcars)

  })
}



# Cicerone ----------------------------------------------------------------

guide <- Cicerone$
  new()$
  step(el = "mainTabs",
       "Main Tabs",
       "These are the main tabs set in the main server")$
  step(el = "tab1-subTabs",
       "Sub Tabs",
       "These are the subtabs under Tab1")$
  step(el = "tab1-chart_1-chart",
       "Chart",
       "This is a chart!")$
  step(el = "tab1-table_1-table",
       "Table",
       "This is a table!",
       tab = "Table",
       tab_id = "tab1-subTabs")$
  step(el = ".form-group.shiny-input-container",
       "Filters",
       "Here you can filter the table by number of cylinders.")


# Main app ----------------------------------------------------------------

ui <- fluidPage(
  use_cicerone(),
  mainPanel(
    tabsetPanel(id = "mainTabs",
                tabPanel("tab1", mod_subtabs_ui("tab1")),
                tabPanel("tab2", mod_subtabs_ui("tab2"))
    )
  )
)

server <- function(input, output, session) {
  
  guide$init()$start()
  
  mod_subtabs_server("tab1")
  outputOptions(output, "tab1-table_1-table", suspendWhenHidden = FALSE)
  mod_subtabs_server("tab2")
  
  
}

shinyApp(ui = ui, server = server)
© www.soinside.com 2019 - 2024. All rights reserved.