在闪亮模块表之间传输行

问题描述 投票:0回答:1

我正在尝试在源数据表和模块中包含的数据表之间移动行。我在过滤 renderDataTable 环境之外的原始表时遇到问题,以便将正确的行传递到模块。现在应用程序正在运行,但使用 _rows_selected 引用了错误的表。

我的计划是使用 .original_order 列作为唯一键。我可以在 UI 中打印此值,但无法在服务器函数中(在 renderDataTable 之外)访问此值。我尝试插入这个:

  filtered_df <- reactive({
    filtered_data <- my_data() %>% filter(cyl >= input$cyl_slide)

    filtered_data
  })

然后在renderDataTable函数中引用filtered_df()而不是my_data(),但出现找不到对象“cyl”的错误。我知道该应用程序并不完美,因为这是我第一次尝试使用模块,并且我改编了here找到的代码,但下面的应用程序确实运行,我只需要调整它即可移动正确的行,即使在过滤时也是如此。

library(shiny)
library(DT)
library("shinydashboard")

receiver_ui <- function(id, class) {
  ns <- NS(id)
  fluidRow(
    column(width = 1,
           actionButton(ns("add"), 
                        label = NULL,
                        icon("angle-right")),
           actionButton(ns("remove"),
                        label = NULL,
                        icon("angle-left")),
           actionButton(ns("remove_all"),
                        label = NULL,
                        icon("angle-double-left"))),
    column(width = 11,
           dataTableOutput(ns("sink_table"))),
    class = class
  )
}

receiver_server <- function(input, output, session, selected_rows, full_page, blueprint) {

  data_exch <- reactiveValues(send    = blueprint,
                              receive = blueprint)
  
  trigger_delete <- reactiveValues(trigger = NULL, all = FALSE)
  
order
  output$sink_table <- renderDataTable({
    dat <- data_exch$receive
    dat$.original_order <- NULL
    dat
  })
  
  shift_rows <- function(selector) {
    data_exch$send <- data_exch$receive[selector, , drop = FALSE]
    data_exch$receive <- data_exch$receive[-selector, , drop = FALSE]
  }
  
  add_rows <- function(all) {
    rel_rows <- if(all) req(full_page()) else req(selected_rows())
    data_exch$receive <- rbind(data_exch$receive, rel_rows)
    data_exch$receive <- data_exch$receive[order(data_exch$receive$.original_order), ]
    ## trigger delete, such that the rows are deleted from the source
    old_value <- trigger_delete$trigger
    trigger_delete$trigger <- ifelse(is.null(old_value), 0, old_value) + 1
    trigger_delete$all <- all
  }
  
  observeEvent(input$add, {
    add_rows(FALSE)
  })
  
  observeEvent(input$add_all, {
    add_rows(TRUE)
  })
  
  observeEvent(input$remove, {
    shift_rows(req(input$sink_table_rows_selected))
  })
  
  observeEvent(input$remove_all, {
    shift_rows(req(input$sink_table_rows_current))
  })
  
  ## this is the original code, attempts to pass a reactive were unsuccessful

  list(send   = reactive(data_exch$send),
       delete = trigger_delete)
}


ui <- fluidPage(
  tags$head(tags$style(HTML(".odd {background: #DDEBF7;}",
                            ".even {background: #BDD7EE;}",
                            ".btn-default {min-width:38.25px;}",
                            ".row {padding-top: 15px;}"))),
  fluidRow(
    actionButton("add", "Add Table") 
  ),
  fluidRow(
    sliderInput("cyl_slide", '', min = 4, max = 8, value = 4)
  ),
  fluidRow(
    column(width = 6, dataTableOutput("source_table")),
    column(width = 6, div(id = "container")),
  ),
  fluidRow(
    box(width = 12,title="Selected ID:",textOutput('id_selected'))
  )
)

orig_data <- mtcars
orig_data$.original_order <- seq(1, NROW(orig_data), 1)
my_data <- reactiveVal(orig_data)

server <- function(input, output, session) {
  #orig_data <- orig_data[orig_data$cyl >= input$cyl_slide,]
  cyl_re <- reactive({input$cyl_slide}) #try this?
   #{orig_data[orig_data$cyl >= cyl_re(),]} why does it need to be reactiveVal and not reactive?
  
  # filtered_df <- reactive({
  #   filtered_data <- my_data() %>% filter(cyl >= input$cyl_slide)
  # 
  #   filtered_data
  # })
  
  handlers <- reactiveVal(list())
  
  selected_rows <- reactive({
    my_data()[req(input$source_table_rows_selected), , drop = FALSE]
  })
  
  all_rows <- reactive({
    my_data()[req(input$source_table_rows_current), , drop = FALSE]
  })
  
  observeEvent(input$add, {
    old_handles <- handlers()
    n <- length(old_handles) + 1
    uid <- paste0("row", n)
    insertUI("#container", ui = receiver_ui(uid, ifelse(n %% 2, "odd", "even")))
    new_handle <- callModule( #I know this is outdated but attempts to reconfigure to moduleServer were unsuccessful because I didn't know where to put the extra arguments (uid, selected_rows,...etc)
      receiver_server,
      uid,
      selected_rows = selected_rows,
      full_page = all_rows,
      ## select 0 rows data.frame to get the structure
      blueprint = orig_data[0, ])
    
    observeEvent(new_handle$delete$trigger, {
      if (new_handle$delete$all) {
        selection <- req(input$source_table_rows_current)
      } else {
        selection <- req(input$source_table_rows_selected)
      }
      my_data(my_data()[-selection, , drop = FALSE])
    })
    
    observe({
      req(NROW(new_handle$send()) > 0)
      dat <- rbind(isolate(my_data()), new_handle$send())
      my_data(dat[order(dat$.original_order), ])
    })
    handlers(c(old_handles, setNames(list(new_handle), uid)))
  })
  
  output$source_table <- renderDataTable({
    dat <- my_data()
    dat <- dat[dat$cyl >= input$cyl_slide,]
    #dat$.original_order <- NULL
    
    output$id_selected = renderText({
      s = input$source_table_rows_selected
      if (length(s)>0 & dat$.original_order[s]!="") {
        dat$.original_order[s]
      }
    })
    
    dat
  })
}


shinyApp(ui, server)
r shiny shinydashboard shiny-reactivity shinymodules
1个回答
0
投票

让我们一步一步来吧,因为我迷路了。这是第一步。现在,你想做什么?

library(shiny)
library(DT)

DATA <- mtcars[, 1:4]

receiver_ui <- function(id) {
  ns <- NS(id)
  fluidRow(
    column(width = 1,
           actionButton(ns("add"), 
                        label = NULL,
                        icon("angle-right"))
    ),
    column(width = 11,
           DTOutput(ns("sink_table")))
  )
}

receiver_server <- function(id, selectedRows) {
  moduleServer(
    id,
    function(input, output, session) {
      
      Dat <- reactiveVal()
      CurrentData <- reactiveVal(DATA)
      
      output$sink_table <- renderDT({
        datatable(Dat())
      })

      missingRows <- reactiveVal(1:nrow(DATA))
      
      observeEvent(input$add, {
        missing_rows <- setdiff(1:nrow(CurrentData()), selectedRows())
        Dat(rbind(Dat(), CurrentData()[selectedRows(), , drop = FALSE]))
        CurrentData(CurrentData()[missing_rows, , drop = FALSE])
        missingRows(missing_rows)
      })
      
      return(missingRows)
      
    }
  )
}

ui <- fluidPage(
  fluidRow(
    sliderInput("cyl_slide", '', min = 4, max = 8, value = 4)
  ),
  fluidRow(
    column(width = 6, DTOutput("source_table")),
    column(width = 6, receiver_ui("x"))
  )
)

server <- function(input, output, session) {
  
  my_data <- reactiveVal(DATA)
  
  output$source_table <- renderDT({
    datatable(my_data())
  })
  
  selectedRows <- eventReactive(input$source_table_rows_selected, {
    input$source_table_rows_selected
  })
#  observeEvent(input$source_table_rows_selected, {
  missingRows <- receiver_server("x", selectedRows)
#  })
  
  observeEvent(missingRows(), {
    my_data(my_data()[missingRows(), , drop = FALSE])
  })
  
}

shinyApp(ui, server)
© www.soinside.com 2019 - 2024. All rights reserved.