代码之家  ›  专栏  ›  技术社区  ›  starja

为什么需要先调用此无功值才能使用它?

  •  0
  • starja  · 技术社区  · 5 年前

    this question ,我偶然发现了以下问题。我有两个不同的模块, inputtable 显示 rhandsontable resulttable 将此表作为输入,执行一些计算并将结果显示为 rhandsontable公司 . 可输入 对象作为无功值。因为每个模块可以有多个副本,所以我存储 可输入 结果表 .

    我注意到了 结果表 ,无功输入 input_data$input_table() 不能直接使用。当我打电话给 browser print

    据我所知,将无功值传递给模块,这应该可以工作,而不需要在使用之前对无功值做其他操作。如果我不使用列表存储无功值,而只使用每个模块的一个副本并直接存储 可输入 并将此传递给 结果表 ,正如我所料。(但是将不同的无功值存储在 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 .

    • 第一个显示的表来自 可输入 i = 2 而不是 i = 1 ,我还不知道为什么。

    所以也许我的代码有其他问题。我很高兴能为这种奇怪的行为提供任何提示,或者如何做一个更简单的例子。

    0 回复  |  直到 5 年前
        1
  •  1
  •   YBS    5 年前

    通过改变 for 循环到 lapply

    ui <- fluidPage(navbarPage("App",
                     
                     tabPanel("Input",
                              sliderInput('num_of_table', "Number of sub tabs: ", value = 1, min = 1, max = 10),
                              #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 <- 0
    
    server <- function(input, output, session) {
      number_modules <- reactiveVal(0)
      # variable to store the inputs from the modules
      input_data <- list()
      
      observeEvent(input$num_of_table, {
        req(input$num_of_table)
        if (input$num_of_table > number_modules() ){
          modules_to_add <- reactive({input$num_of_table - number_modules()})
        }else {
          modules_to_add <- reactive({0})
        }
        lapply(1:modules_to_add(), function(i) {
          # update the id
          current_id <<- current_id + 1
          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
          if (input$num_of_table > number_modules() ){
            appendTab(inputId = "insert_input",
                      tab = inputtableUI(paste0("inputtable_", current_id)))
            appendTab(inputId = "insert_results",
                      tab = resulttableUI(paste0("resulttable_", current_id)))
          }
          
        })
        
        if (input$num_of_table > number_modules() ){
          number_modules(input$num_of_table)
          updateTabsetPanel(session,
                            "insert_input",
                            "inputtable_1-inputtable_1")
        }
        
      })
    }
    

    如果为“表的num_”选择了一个较高的数字,那么在input table为所有子选项卡显示最后一个表时,可能仍然需要更新显示的内容。