簡體   English   中英

R Shiny模塊在同一事件中未響應更新

[英]R Shiny module not updating reactively within same event

在R中使用模塊時, 我的反應性存在問題。 如果我更新一個模塊,然后嘗試使用這些更新的值更新另一個模塊,我會在更新之前獲取這些值。

我已經寫了一些基本代碼來說明我的意思。 在這里,我有一個應用程序,該應用程序更新放置在名為my_module的模塊中的rHandsontableOutput ,然后在按下按鈕時將此更新的rHandsontableOutput復制到第二個模塊module_to_update

我發現的是my_module中的第一個表將更新,而module_to_update中的第一個表不會更新。 相反, module_to_update表將在更新之前收到my_module初始表的副本。 如果我再次按下更新按鈕,則一切正常。

我猜測這與我如何處理會話或響應值有關,但我沒有主意。

問題 :如何設置反應值和模塊,以便可以在同一函數調用中對更新的模塊數據運行操作? (例如,請參見下面的observeEvent(input$update_btn, ...)調用)

圖片: 更新的表未復制

application.R

library(shiny)
library(rhandsontable)

source('my_modules.R')

active_tab = ""

ui <- navbarPage("Module Test Tool",

             tabsetPanel(id = 'mainTabset',
                         tabPanel("My Tab",

                                  #This is the HoT that works as expected, updating when called upon
                                  h4("Table 1"),
                                  myModuleUI('my_module'),
                                  #This is the HoT that does NOT work as expected. This HoT fails to use the updated values from 'my_module' HoT
                                  h4("Table to be updated"),
                                  myModuleUI('module_to_update'),
                                  br(),
                                  br(),

                                  fluidRow(
                                    #this button updates tables to new values
                                    actionButton("update_btn", "Update and Add Tables"),
                                    br(),
                                    br(),
                                    textOutput('table1_sum'),
                                    textOutput('table2_sum'),
                                    br(),
                                    br()
                                  )
                         )
             )

)


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

  #Link logic for tab module
  callModule(myModule, 'my_module')



  #This button sums up all the rHandsonTable data frames
  observeEvent(input$update_btn, {


    #Update values in table and integer drop down list before doing basic operations on them
    #New values should be all 5s
    five_col = rep(5,3)
    callModule(updateModule, 'my_module', 5, data.frame(col1 = five_col,
                                                          col2 = five_col,
                                                          col3 = five_col))



    #Grabs updated module table and does operations on it
    module_data = callModule(getMyModuleData, 'my_module')
    module_int= module_data$module_int
    module_df = module_data$module_df

    output$table1_sum = renderText({
      paste0("Sum of Table 1 is: ", sum(module_df())," | The selected integer is: ", module_int())
    })

    #------------------------------------------------------
    #------------------ERROR BELOW-------------------------
    #------------------------------------------------------
    #THIS IS THE CODE THAT FAILS. This updates a 2nd module that should mirror the updated values. However, this results in old values.
    callModule(updateModule, 'module_to_update', module_int(), module_df())

    #Tries to call on new, updated table
    updated_module_data = callModule(getMyModuleData, 'module_to_update')
    updated_module_int= updated_module_data$module_int
    updated_module_df = updated_module_data$module_df

    #Display results of basic operations on new table
    output$table2_sum = renderText({
      paste0("Sum of Updated Table is: ", sum(updated_module_df())," | The selected integer is: ", updated_module_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) {

  one_col = rep.int('VALUE AT INITIALIZATION',3)
  df = data.frame(col1 = one_col,
                  col2 = one_col,
                  col3 = one_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_df = reactive({hot_to_r(input$module_hot)}),
        module_int =  reactive({input$module_int_list})
    )
  )
}

updateModule<- function(input,output,session, new_integer, new_dataframe){
  if(!is.null(new_dataframe))
  {
    output$module_hot <- renderRHandsontable({
      rhandsontable(new_dataframe, stretchH = "none", rowHeaders = NULL)
    })
  }

  outputOptions(output, "module_hot", suspendWhenHidden = FALSE)

  updateSelectInput(session, "module_int_list",selected = new_integer)
}


這里有一些問題...

您正在使用相同的名稱空間調用多個不同的模塊。 模塊應該彼此獨立運行。 它們每個都應具有自己的名稱空間。 以下是不正確的:

callModule(myModule, 'my_module') 

callModule(updateModule, 'my_module', 5, data.frame(col1 = five_col,
                                                          col2 = five_col,
                                                          col3 = five_col))

module_data = callModule(getMyModuleData, 'my_module')

您正在從observeEvent()中調用模塊。 這意味着每次觀察到該事件時,您都會嘗試初始化該模塊。 您不想初始化模塊,而是想將新變量傳遞給該模塊。 如果使模塊返回其值,則將這些返回的值用作另一個模塊的輸入,您將不需要觀察該事件……接收新信息的模塊將決定是否觀察該變化。

您已經創建了一個函數/模塊getMyModuleData ,該函數/模塊僅應返回存在於其他模塊中的數據。 相反,您應該讓另一個模塊返回所需的數據。

檢出: https : //shiny.rstudio.com/articles/communicate-bet-modules.html

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM