从另一个 tabPanel 调用时,rHandsonTable 模块返回 NULL
rHandsonTable module returning NULL when called from another tabPanel
我有一个应用程序在使用 tabPanel
的模块中使用 rHandsonTableOutput
(HoT)。虽然出于某种原因我可以从此模块获取其他数据(例如在 selectInput
中进行的选择),但在尝试获取 HoT
数据时我得到了 NULL。我制作了一个非常简单的代码版本来说明我的意思。
我发现如果我将模块放在同一个 UI 元素中,则可以访问 HoT
数据。出于某种原因,如果我将它放在 tabPanel
中的另一个选项卡中,它无法 return 数据。我的示例代码应在此处显示。
更新 - 我发现只要我先点击并加载有问题的 HoT
选项卡,该模块就可以正常工作!关于 "viewing" 标签的一些事情似乎首先解决了这个问题。我很想找到一种不需要这样做的方法。这与 rshiny "sessions" 相关吗?
下面是应该重现错误的代码。您会发现一个包含两个 HoT
的简单应用程序。主选项卡通过模块 myModuleUI
放入了一个。还有第二个下拉选项卡,其中包含通过第二个模块 myModuleTabUI
生成的第二个 HoT
。除了 myModuleTabUI
将所有内容都放在 tabPanel
之外,它们是相同的。如果您按 "Add Table Button" 它只是将表格中的数字相加,但是当尝试对 ID 为 first_tab 的 HoT
这样做时会失败(即在另一个选项卡中找到的 HoT
)。
这包含闪亮的主要应用程序
application.R
library(shiny)
library(rhandsontable)
source('my_modules.R')
ui <- navbarPage("Module Test Tool",
tabsetPanel(id = 'mainTabset',
tabPanel("My Tab",
#This is the HoT that is accessible from a module
h4("Table 1"),
myModuleUI('my_module'),
br(),
br(),
fluidRow(
actionButton("sum_btn", "Add table data"),
br(),
br(),
textOutput('table1_sum'),
textOutput('table2_sum'),
br(),
br()
)
),
navbarMenu("My Module Tabs",
#This is the HoT that is inaccessible from a module
myModuleTabUI('first_tab', 'First')
)
)
)
server <- function(input, output, session) {
#Link logic for tab module
callModule(myModule, 'my_module')
callModule(myModuleTab, 'first_tab')
one_col = rep.int(1,3)
df = data.frame(col1 = one_col,
col2 = one_col,
col3 = one_col)
output$hot <- renderRHandsontable({
rhandsontable(df, stretchH = "none", rowHeaders = NULL)
})
#This button sums up all the rHandsonTable data frames
observeEvent(input$sum_btn, {
#Works just fine when not pulling from the same panel's module
module_data = callModule(getMyModuleData, 'my_module')
module_int= module_data$module_int
module_df = module_data$module_hot
output$table1_sum = renderText({
paste0("Sum of Table 1 is: ", sum(module_df)," | Integer one is: ", module_int)
})
#Fails when pulling a hands on table from another tab
module_tab_data = callModule(getMyModuleTabData, 'first_tab') #<---THIS LINE FAILS
module_tab_int= module_tab_data$module_tab_int
module_tab_df = module_tab_data$module_tab_hot
output$table2_sum = renderText({
paste0("Sum of the table in the 'First' tab is: ", sum(module_tab_df)," | Integer in 'First' tab is: ", module_tab_int)
})
})
}
## Create Shiny app ----
shinyApp(ui, server)
此文件包含此示例中使用的模块:
my_modules.R
#Simple module containing one rHandsontable and a drop down list of integers
myModuleUI <- function(id,tab_name){
ns <- NS(id)
fluidRow(
rHandsontableOutput(ns("module_hot")),
selectInput(ns('module_int_list'),"Integers:",c(1:5), selected = 1)
)
}
#Initializes myModuleUI rHandsonTable with some values
myModule <- function(input, output, session) {
two_col = rep.int(2,3)
df = data.frame(col1 = two_col,
col2 = two_col,
col3 = two_col)
output$module_hot <- renderRHandsontable({
rhandsontable(df, stretchH = "none", rowHeaders = NULL)
})
}
#Returns myModule data for use outside of the module
getMyModuleData <- function(input,output,session){
return (
list(
module_hot = hot_to_r(input$module_hot),
module_int = input$module_int_list
)
)
}
#Simple module that adds the same as MyModuleUI, except in a tabPanel
myModuleTabUI <- function(id,tab_name){
ns <- NS(id)
tabPanel(tab_name,
fluidRow(
rHandsontableOutput(ns("module_tab_hot")),
selectInput(ns('module_tab_int_list'),"Integers:",c(1:5), selected = 1)
)
)
}
#Initializes myModuleTabUI rHandsonTable with some values
myModuleTab <- function(input, output, session){
three_col = rep.int(3,3)
df = data.frame(col1 = three_col,
col2 = three_col,
col3 = three_col)
output$module_tab_hot <- renderRHandsontable({
rhandsontable(df, stretchH = "none", rowHeaders = NULL)
})
}
#Returns MyModuleTab data for use outside of the module
getMyModuleTabData <- function(input,output,session){
return (
list(
module_tab_hot = hot_to_r(input$module_tab_hot), #<---THIS LINE FAILS
module_tab_int = input$module_tab_int_list
)
)
}
请编辑这些行:
#Fails when pulling a hands on table from another tab
module_tab_dat = callModule(getMyModuleTabData, 'first_tab') #<---THIS LINE FAILS
module_tab_int= module_tab_dat$module_tab_int
module_tab_df = module_tab_dat$module_tab_hot
您有:
module_tab_int= module_data$module_tab_int
module_tab_df = module_data$module_tab_hot
但是您将模块命名为 module_tab_dat
。我假设复制粘贴错误。
更新
关于您的更新,请在您的模块代码中添加此行:
output$module_tab_hot <- renderRHandsontable({
rhandsontable(df, stretchH = "none", rowHeaders = NULL)
})
# Added line
outputOptions(output, "module_tab_hot", suspendWhenHidden = FALSE)
默认情况下 suspendWhenHidden
的恰当命名是 TRUE
,这对于大多数用例来说可能是正确的。在这种情况下,它必须是 FALSE
。参见 here
我有一个应用程序在使用 tabPanel
的模块中使用 rHandsonTableOutput
(HoT)。虽然出于某种原因我可以从此模块获取其他数据(例如在 selectInput
中进行的选择),但在尝试获取 HoT
数据时我得到了 NULL。我制作了一个非常简单的代码版本来说明我的意思。
我发现如果我将模块放在同一个 UI 元素中,则可以访问 HoT
数据。出于某种原因,如果我将它放在 tabPanel
中的另一个选项卡中,它无法 return 数据。我的示例代码应在此处显示。
更新 - 我发现只要我先点击并加载有问题的 HoT
选项卡,该模块就可以正常工作!关于 "viewing" 标签的一些事情似乎首先解决了这个问题。我很想找到一种不需要这样做的方法。这与 rshiny "sessions" 相关吗?
下面是应该重现错误的代码。您会发现一个包含两个 HoT
的简单应用程序。主选项卡通过模块 myModuleUI
放入了一个。还有第二个下拉选项卡,其中包含通过第二个模块 myModuleTabUI
生成的第二个 HoT
。除了 myModuleTabUI
将所有内容都放在 tabPanel
之外,它们是相同的。如果您按 "Add Table Button" 它只是将表格中的数字相加,但是当尝试对 ID 为 first_tab 的 HoT
这样做时会失败(即在另一个选项卡中找到的 HoT
)。
这包含闪亮的主要应用程序
application.R
library(shiny)
library(rhandsontable)
source('my_modules.R')
ui <- navbarPage("Module Test Tool",
tabsetPanel(id = 'mainTabset',
tabPanel("My Tab",
#This is the HoT that is accessible from a module
h4("Table 1"),
myModuleUI('my_module'),
br(),
br(),
fluidRow(
actionButton("sum_btn", "Add table data"),
br(),
br(),
textOutput('table1_sum'),
textOutput('table2_sum'),
br(),
br()
)
),
navbarMenu("My Module Tabs",
#This is the HoT that is inaccessible from a module
myModuleTabUI('first_tab', 'First')
)
)
)
server <- function(input, output, session) {
#Link logic for tab module
callModule(myModule, 'my_module')
callModule(myModuleTab, 'first_tab')
one_col = rep.int(1,3)
df = data.frame(col1 = one_col,
col2 = one_col,
col3 = one_col)
output$hot <- renderRHandsontable({
rhandsontable(df, stretchH = "none", rowHeaders = NULL)
})
#This button sums up all the rHandsonTable data frames
observeEvent(input$sum_btn, {
#Works just fine when not pulling from the same panel's module
module_data = callModule(getMyModuleData, 'my_module')
module_int= module_data$module_int
module_df = module_data$module_hot
output$table1_sum = renderText({
paste0("Sum of Table 1 is: ", sum(module_df)," | Integer one is: ", module_int)
})
#Fails when pulling a hands on table from another tab
module_tab_data = callModule(getMyModuleTabData, 'first_tab') #<---THIS LINE FAILS
module_tab_int= module_tab_data$module_tab_int
module_tab_df = module_tab_data$module_tab_hot
output$table2_sum = renderText({
paste0("Sum of the table in the 'First' tab is: ", sum(module_tab_df)," | Integer in 'First' tab is: ", module_tab_int)
})
})
}
## Create Shiny app ----
shinyApp(ui, server)
此文件包含此示例中使用的模块:
my_modules.R
#Simple module containing one rHandsontable and a drop down list of integers
myModuleUI <- function(id,tab_name){
ns <- NS(id)
fluidRow(
rHandsontableOutput(ns("module_hot")),
selectInput(ns('module_int_list'),"Integers:",c(1:5), selected = 1)
)
}
#Initializes myModuleUI rHandsonTable with some values
myModule <- function(input, output, session) {
two_col = rep.int(2,3)
df = data.frame(col1 = two_col,
col2 = two_col,
col3 = two_col)
output$module_hot <- renderRHandsontable({
rhandsontable(df, stretchH = "none", rowHeaders = NULL)
})
}
#Returns myModule data for use outside of the module
getMyModuleData <- function(input,output,session){
return (
list(
module_hot = hot_to_r(input$module_hot),
module_int = input$module_int_list
)
)
}
#Simple module that adds the same as MyModuleUI, except in a tabPanel
myModuleTabUI <- function(id,tab_name){
ns <- NS(id)
tabPanel(tab_name,
fluidRow(
rHandsontableOutput(ns("module_tab_hot")),
selectInput(ns('module_tab_int_list'),"Integers:",c(1:5), selected = 1)
)
)
}
#Initializes myModuleTabUI rHandsonTable with some values
myModuleTab <- function(input, output, session){
three_col = rep.int(3,3)
df = data.frame(col1 = three_col,
col2 = three_col,
col3 = three_col)
output$module_tab_hot <- renderRHandsontable({
rhandsontable(df, stretchH = "none", rowHeaders = NULL)
})
}
#Returns MyModuleTab data for use outside of the module
getMyModuleTabData <- function(input,output,session){
return (
list(
module_tab_hot = hot_to_r(input$module_tab_hot), #<---THIS LINE FAILS
module_tab_int = input$module_tab_int_list
)
)
}
请编辑这些行:
#Fails when pulling a hands on table from another tab
module_tab_dat = callModule(getMyModuleTabData, 'first_tab') #<---THIS LINE FAILS
module_tab_int= module_tab_dat$module_tab_int
module_tab_df = module_tab_dat$module_tab_hot
您有:
module_tab_int= module_data$module_tab_int
module_tab_df = module_data$module_tab_hot
但是您将模块命名为 module_tab_dat
。我假设复制粘贴错误。
更新
关于您的更新,请在您的模块代码中添加此行:
output$module_tab_hot <- renderRHandsontable({
rhandsontable(df, stretchH = "none", rowHeaders = NULL)
})
# Added line
outputOptions(output, "module_tab_hot", suspendWhenHidden = FALSE)
默认情况下 suspendWhenHidden
的恰当命名是 TRUE
,这对于大多数用例来说可能是正确的。在这种情况下,它必须是 FALSE
。参见 here