Пытаясь придумать слишком сложное решение для этого вопроса , я наткнулся на следующую проблему. У меня есть 2 разных модуля, inputtable
отображает rhandsontable
и возвращает эту таблицу, а resulttable
принимает эту таблицу в качестве входных данных, выполняет некоторые вычисления и отображает результат как rhandsontable
. inputtable
возвращает объект rhandsontable
как реактивное значение. Поскольку может быть несколько копий каждого модуля, я сохраняю результаты из inputtable
в списке и передаю элементы списка в качестве входных в resulttable
.
Я заметил, что в resulttable
, реактивный вход input_data$input_table()
не может использоваться напрямую. Когда я вызываю функцию browser
или print
или назначаю ее переменной до того, как использую реактивное значение для фактической цели, тогда она работает. В противном случае я получаю сообщение об ошибке
попытка применить нефункцию
Насколько я понял, передача реактивных значений в модули, это должно работать без необходимости делать что-то еще до реактивного значения перед его использованием. Если я не использую список для хранения реактивного значения, а использую только одну копию каждого модуля и напрямую сохраняю результат inputtable
в переменной и передаю его в resulttable
, он работает так, как я ожидал. (Но сохранение различных реактивных значений в объекте reactiveValues
также приводит к ошибке.)
Кто-нибудь знает, что там происходит?
Прошу прощения за длинный пример, когда я пытался сократить, я потерял ошибку:
library(shiny)
library(rhandsontable)
# define the first module
resulttableUI <- function(id) {
ns <- NS(id)
tabPanel(title = ns(id),
column(12,
rHandsontableOutput(ns("results_table"))))
}
resulttable <- function(id, input_data) {
moduleServer(
id,
function(input, output, session) {
# THE NEXT LINE NEEDS TO BE UNCOMMENTED TO MAKE IT WORK
# used_data <- input_data$input_table()
output$results_table <- renderRHandsontable({
rhandsontable(hot_to_r(input_data$input_table())[2:5]/hot_to_r(input_data$input_table())[1:4])
})
}
)
}
# define the second module
inputtableUI <- function(id) {
ns <- NS(id)
tabPanel(title = ns(id),
column(12,
rHandsontableOutput(ns("input_table"))))
}
inputtable <- function(id, i) {
moduleServer(
id,
function(input, output, session) {
output$input_table <- renderRHandsontable({
mat <- matrix(c(1:25) * i, ncol = 5, nrow = 5)
mat <- as.data.frame(mat)
rhandsontable(mat)
})
return(list(
input_table = reactive({input$input_table})
))
}
)
}
ui <- navbarPage("App",
tabPanel("Input",
numericInput('num_of_table', "Number of sub tabs: ", value = 1, min = 1, max = 10),
tabsetPanel(id = "insert_input")),
tabPanel("Results",
tabsetPanel(id = "insert_results"))
)
number_modules <- 0
current_id <- 1
server <- function(input, output, session) {
# variable to store the inputs from the modules
input_data <- list()
observeEvent(input$num_of_table, {
modules_to_add <- input$num_of_table - number_modules
for (i in seq_len(modules_to_add)) {
# add the logic for the input
input_data[[paste0("inputtable_", current_id)]] <<-
inputtable(paste0("inputtable_", current_id), current_id)
# add the logic for the results
resulttable(paste0("resulttable_", current_id),
input_data = input_data[[paste0("inputtable_", current_id)]])
# add the UI
appendTab(inputId = "insert_input",
tab = inputtableUI(paste0("inputtable_", current_id)))
appendTab(inputId = "insert_results",
tab = resulttableUI(paste0("resulttable_", current_id)))
# update the id
current_id <<- current_id + 1
}
number_modules <<- input$num_of_table
updateTabsetPanel(session,
"insert_input",
"inputtable_1-inputtable_1")
})
}
shinyApp(ui,server)
Я использую R 3.6.1
и shiny 1.5.0
.
К сожалению, есть еще 2 проблемы:
- Вам нужно щелкнуть вкладку результатов, чтобы отобразить его.
- Первая показанная таблица из модуля
inputtable
использует i = 2
вместо i = 1
, я еще не понял почему.
Возможно, с моим кодом что-то не так. Я рад любым подсказкам об этом странном поведении или о том, как сделать более простой пример.