0

Not a Shiny programmer. Simple question. rhandsontable in Flexdashboard app. How to access a column updated by the user? Sample code:

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

```{r setup, include=FALSE}
library(flexdashboard)
library(shiny)
require(dplyr)
require(tidyverse)
require(rhandsontable)

hour <- 1:24
required <- c(2, 2, 2, 2, 2, 2, 8, 8, 8, 8, 4, 4, 3, 3, 3, 3, 6, 6, 5, 5, 5, 5, 3, 3)
required <- as.integer(required)
on_duty <- as.integer(rep(0, 24))
start <- on_duty

df <- data.frame(hour, required, on_duty, start)

```
Inputs {.sidebar data-width=w}
-----------------------------------------------------------------------

```{r Inputs}

```

Column {data-width=200}
-----------------------------------------------------------------------

### Chart A

```{r}

global <- reactiveValues(df = df)

rHandsontableOutput("dftbl1")

    output$dftbl1 = renderRHandsontable({
    rhandsontable(global$df, selectCallback = TRUE, readOnly = FALSE)
    })

```

So the code renders the table. A user could update the table by editing the table cells. But then how to reference the updated table to pass table columns to a function called with an actionButton? The complex examples I've found are difficult to decipher. Appreciate any feedback. SteveM

SteveM
  • 2,226
  • 3
  • 12
  • 16

1 Answers1

4

you can use hot_to_r as in

modified_table <- reactive({
  hot_to_r(req(input$table_id)) ## req!
})

to get access to the current state of the table including modifications from the user. req is needed because hot_to_r can't deal with NULLs. table_id should be the output-id you use for the return value of renderRHandsontable.

output$table_id <- renderRHandsontable({ 
  rhandsontable(initial_table) ## need to call converter
})

The complex examles you are referring to (like this one, #64-81) allow a two-way connection of the tables in the sense that they can be updated both from the user and from the server. In this simple setup I outlined here however, modified_table is created with reactive so it can only be updated by the user.

I totally agree that this package could be made more user friendly by allowing NULL in hot_to_r and by automatically calling rhandsontable in renderRHandsontable if the return value is a data.frame but this is what you will have to work with.

Here is a full app demonstrating this setup

library(shiny)
library(rhandsontable)

ui <- fluidPage(
  rHandsontableOutput("table_id"),
  tableOutput("second_table")
)

server <- function(input, output, session) {
  initial_table <- head(iris)

  output$table_id <- renderRHandsontable({
    rhandsontable(initial_table) ## need to call converter
  })

  modified_table <- reactive({
    hot_to_r(req(input$table_id)) ## req!
  })

  output$second_table <- renderTable({
    modified_table()
  })
}

shinyApp(ui, server)

In order to access a specific column, you can use modified_table()$column_name inside a reactive context.

Gregor de Cillia
  • 7,397
  • 1
  • 26
  • 43
  • Great. Works perfectly. – SteveM Dec 11 '18 at 16:09
  • The answer above does allow a user to edit the table (thanks). I tested the table updating using a renderValueBox that displays the sum of the entries of a column in the table. When a table column cell is changed, the change is reflected in the ValueBox. However, when I pass the updated table column to a function that executes an algorithm, the original data column is used in the calculations. The function does return the table with result outputs from the algorithm in other table columns. So the algorithm is processing, but using the original input data column. Any additional advice? – SteveM Dec 12 '18 at 17:42
  • 1
    It depends on the context in which you are calling the function. If it is inside a `renderXXX` function as in `renderText({myFun(modified_table())})` everything should work fine. Otherwise, you should probably use another call to the function `reactive` to cache the return values of `myFun`. – Gregor de Cillia Dec 12 '18 at 18:25
  • Gregor, thanks for the reply. I was passing the wrong variable to my function. Passing the modified_table() works, so your solution is completely correct. Much appreciated. SteveM – SteveM Dec 13 '18 at 18:15
  • This worked for me to, but I have a tangential question: I am not sure I understand how `input` and `output` work in flexdashboard/rmarkdown_shiny. Does anyone have a good link where I can read about it? – mic Jan 06 '21 at 22:18