【问题标题】:How to avoid module code being run prematurely? [duplicate]如何避免模块代码过早运行? [复制]
【发布时间】:2019-05-13 15:32:33
【问题描述】:

我有一个使用模块概念的应用程序,其中基本上每个tabPanel 都是它自己的模块。我进行了设置,以便每个模块从光盘中读取自己的数据集。问题是我希望能够使用该数据集动态填充模块中的选择输入。这很容易实现,但问题是当我在模块中填充选择输入时,使用updateSelectInput() 这会触发模块数据读取,以便在应用程序加载时运行,而不是在打开/导航到模块时运行。

我创建了一个小示例来说明dat() 是如何过早运行的。在我的实际项目中,这是一个大问题,因为这意味着所有数据都是预先加载的,而不是在导航到时加载,这使得它非常缓慢且效率低下。

有什么办法可以避免这种情况吗?

library(shiny)
library(dplyr)

module_ui <- function(id, ...) {
    ns <- NS(id)

    tagList(
        "This is the module UI.",
        selectInput(ns("model"), "Select car model:", choices = NULL),
        textOutput(ns("result"))
        )
}

module_server <- function(input, output, session, ...) {

    dat <- reactive({
        # this is where data would be read from disc
        print("Data reading triggered!")
        out <- rownames_to_column(tbl_df(mtcars), "model")
        out
    })

    output$result <- renderText({
        paste("Miles per gallon is", pull(filter(out, model == input$model), "mpg"))
    })


    observe({
        updateSelectInput(session, inputId = "model", choices = dat()$model)
    })
}

ui <- navbarPage("App Title",
                 tabPanel("Tab A", "This is just a landing page."),
                 tabPanel("Tab B", module_ui(id = "my_module"))
)

server <- function(input, output) {

    callModule(module = module_server, id = "my_module")
}

shinyApp(ui = ui, server = server)

【问题讨论】:

  • 所以在您的情况下,您希望在选择新的tabPanel() 时运行该模块?
  • This 可能感兴趣。
  • @ismirsehregal 良好的链接。那么它不是重复的(navbarPage 和 menuItem 都由 id 引用),..
  • 是的,几乎一样。

标签: r shiny


【解决方案1】:

改编自我的回答here(您的navbarPage 需要id):

library(shiny)
library(dplyr)
library(tibble)

print(paste("App start:", Sys.time()))

module_ui <- function(id, ...) {
  ns <- NS(id)

  tagList(
    "This is the module UI.",
    selectInput(ns("model"), "Select car model:", choices = NULL),
    textOutput(ns("result"))
  )
}

module_server <- function(input, output, session, ...) {

  dat <- reactive({
    # this is where data would be read from disc
    print(paste(Sys.time(), "Data reading triggered!"))
    out <- rownames_to_column(tbl_df(mtcars), "model")
    out
  })

  output$result <- renderText({
    paste("Miles per gallon is", pull(filter(dat(), model == input$model), "mpg"))
  })

  observe({
    updateSelectInput(session, inputId = "model", choices = dat()$model)
  })
}

ui <- navbarPage("App Title", id = "navbarID",
                 tabPanel("Tab A", "This is just a landing page."),
                 tabPanel("Tab B", module_ui(id = "my_module"))
)

server <- function(input, output) {

  observeEvent({input$navbarID=="Tab B"},{
      callModule(module = module_server, id = "my_module")
  }, once = TRUE, ignoreInit = TRUE)
}

shinyApp(ui = ui, server = server)

【讨论】:

  • 谢谢!但是,这确实会产生一个新问题,callModule每次都会运行该选项卡,并且每次都会触发数据!有什么想法吗?
  • @jenswirf,您可以为每个选项卡使用observeEvent 并设置once = TRUE,请参阅我的编辑。
【解决方案2】:

尝试以下方法:

  1. 提供 sidebarMenu 和 id,例如。 id = "标签"
  2. 做一个观察者: 测试
observeEvent(input$tabs, {
    if(input$tabs == "tabID"){     
        # Do something     
    }     
})   

用您希望加载数据的选项卡的 ID 替换“tabID”。

【讨论】:

  • 我不明白为什么需要ignoreInit = TRUE
猜你喜欢
  • 2015-05-03
  • 2023-03-24
  • 2019-02-26
  • 1970-01-01
  • 2020-11-22
  • 2020-02-14
  • 2019-12-02
  • 2011-08-29
  • 1970-01-01
相关资源
最近更新 更多