闪亮模块内的可编辑 DT

editable DT inside shiny module

我想在闪亮的模块中有一个 editable DT。当我更改 DT 中的值时,table 更新并且它是空的,数据中的消息 table:

"No matching records found"

我的代码如下:

模块:

modDtUi <- function(id){ # UI module
  ns = NS(id)
  DT::dataTableOutput(ns('x1'))
} 


modDt <-  function(input, output, session, data){ # Server module

  x <- data
  output$x1 <- DT::renderDataTable(x, selection = 'none', editable = TRUE)

  proxy <- dataTableProxy('x1', session = session)

  observeEvent(input$x1_cell_edit, {
    info = input$x1_cell_edit
    str(info)
    print(info)
    i = info$row
    j = info$col
    v = info$value
    x[i, j] <<- DT::coerceValue(v, x[i, j])
    replaceData(proxy, x, resetPaging = FALSE, rownames = FALSE)
  })

}

flexdashboard 中的应用程序:

```{r}
modDtUi("editable")
```

```{r}
callModule(modDt,"editable", data = iris)
```

它在没有模块的情况下工作得很好,但我无法通过闪亮的模块获得相同的结果。

谢谢

以下为我提供了一个 editable table 并在反应中捕获编辑后的 ​​table 以便在应用程序中进一步使用:

library(shiny)
library(DT)

modDtUi <- function(id){ # UI module
  ns = NS(id)
  DT::dataTableOutput(ns('x1'))
}


modDt <-  function(input, output, session, data){ # Server module

  output$x1 <- DT::renderDataTable(data, selection = 'none', editable = TRUE, server = TRUE)
  proxy <- dataTableProxy('x1', session = session)

  updatedData <- eventReactive(input$x1_cell_edit, {
    info = input$x1_cell_edit
    if (!is.null(info)) {
      str(info)
      data[info$row, info$col] <<- DT::coerceValue(info$value,
                                                   data[info$row, info$col])
    }
    data
  }, ignoreNULL = FALSE)

  return(updatedData)
}

ui <- fluidPage(
  modDtUi("editable"),
  tags$hr(),
  "Proof it works: the table below updates on edit.",
  shiny::tableOutput("proof")
)

server <- function(input, output) {
  editable_dt <- callModule(modDt,"editable", data = iris)

  output$proof <- renderTable({
    editable_dt() %>%
      summarise_if(is.numeric, mean)
  })

}

shinyApp(ui = ui, server = server)

如果您删除 rownames = FALSE:

,这会起作用
replaceData(proxy, x, resetPaging = FALSE)#, rownames = FALSE)

如果您不需要行名称,您还必须在 renderDataTable:

中设置 rownames = FALSE
  output$x1 <- DT::renderDataTable(x, selection = 'none', editable = TRUE, 
                                   rownames = FALSE)

然后你必须添加 1info$col:

  observeEvent(input$x1_cell_edit, {
    info = input$x1_cell_edit
    i = info$row
    j = info$col + 1
    v = info$value
    x[i, j] <<- DT::coerceValue(v, x[i, j])
    replaceData(proxy, x, resetPaging = FALSE, rownames = FALSE)
  })

Rmd flexdashboard 的完整代码:

---
title: "Untitled"
output: 
  flexdashboard::flex_dashboard:
    orientation: columns
    vertical_layout: fill
runtime: shiny
---

```{r setup, include=FALSE}
library(flexdashboard)
library(DT)

modDtUi <- function(id){ # UI module
  ns = NS(id)
  DT::dataTableOutput(ns('x1'))
} 

modDt <-  function(input, output, session, data){ # Server module

  x <- data
  output$x1 <- DT::renderDataTable(x, selection = 'none', editable = TRUE, 
                                   rownames = FALSE)

  proxy <- dataTableProxy('x1', session = session)

  observeEvent(input$x1_cell_edit, {
    info = input$x1_cell_edit
    i = info$row
    j = info$col + 1
    v = info$value
    x[i, j] <<- DT::coerceValue(v, x[i, j])
    replaceData(proxy, x, resetPaging = FALSE, rownames = FALSE)
  })

}
```

Column {data-width=650}
-----------------------------------------------------------------------

### Editable table

```{r}
modDtUi("editable")
```

```{r}
callModule(modDt, "editable", data = iris)
```

根据您的代码,问题是代理需要全局会话(而不是模块会话)。请参阅我的其他答案以了解替代方法。

您可以简单地将全局 session 通过参数传递给模块。

这个有效:

library(shiny)
library(DT)

modDtUi <- function(id){ # UI module
  ns = NS(id)
  DT::dataTableOutput(ns('x1'))
}


modDt <-  function(input, output, session, data, globalSession){ # Server module

  x <- data
  output$x1 <- DT::renderDataTable(x, selection = 'none', editable = TRUE)

  proxy <- dataTableProxy('x1', session = globalSession)

  observeEvent(input$x1_cell_edit, {
    info = input$x1_cell_edit
    str(info)
    print(info)
    i = info$row
    j = info$col
    v = info$value
    x[i, j] <<- DT::coerceValue(v, x[i, j])
    replaceData(proxy, x, resetPaging = FALSE)
  })

}

您现在必须在模块调用中添加全局会话。

有了闪亮的应用程序:

ui <- fluidPage(
  modDtUi("editable")
)

server <- function(input, output, session) {
  callModule(modDt,"editable", data = iris, globalSession = session)
}

shinyApp(ui = ui, server = server)

使用 flexdashboard:

```{r}
modDtUi("editable")
```

```{r}
callModule(modDt, "editable", data = iris, globalSession = session)
```

如果您想在应用程序的其余部分使用更新后的 table,只需从模块中 return reactive(x) 并在调用模块时捕获它。

editable_iris <- callModule(modDt,"editable", data = iris, globalSession = session)