Shiny reactive value error, table in module not responding to selectInput choice (input$var)

Hi,

Recently I've been trying to develop a Shiny App that uses 2 imported tables and creates a 3rd table that reflects the sum of the first two tables. In addition, I'm also trying to filter the imported tables by an input$choice from a selectInput expression.

The problem I'm currently running into is this line within the table modules:

data <- reactiveValues(table = test[test$num == reactive({input$var}),])

The code will run if I replace the reactive({input$var}) with an integer that exists within test$num, so I guess I'm just not sure how to call on the input$var value as an integer? Can anyone help me with this problem? The code is below and using an edited mtcars dataset from base R.

### Libraries
library(shiny)
library(dplyr)
library(DT)

### Data----------------------------------------
set.seed(0)
x <- data.frame(num = rep(c(1:5),2))
test <- cbind(mtcars, x)

module1 <- function(id) {
  moduleServer(
    id,
    function(input, output, session) {
      # initialise the reactive data object for the table
      data <- reactiveValues(table = test[test$num == reactive({input$var}),])
      
      # render the table
      output$table <- renderDT({
        datatable(data$table,
                  editable = TRUE)
      })
      
      # update the underlying data
      observeEvent(input$table_cell_edit, {
        data$table <- editData(data$table, input$table_cell_edit)
      })
      
      # return the data as a reactive
      return(reactive(data$table))
    }
  )
}

module2 <- function(id) {
  moduleServer(
    id,
    function(input, output, session) {
      # initialise the reactive data object for the table
      data <- reactiveValues(table = test[test$num == reactive({input$var}),])
      
      # render the table
      output$table <- renderDT({
        datatable(data$table,
                  editable = TRUE)
      })
      
      # update the underlying data
      observeEvent(input$table_cell_edit, {
        data$table <- editData(data$table, input$table_cell_edit)
      })
      
      # return the data as a reactive
      return(reactive(data$table))
    }
  )
}

module_add <- function(id, data_input_1, data_input_2) {
  moduleServer(
    id,
    function(input, output, session) {
      # do the calculations
      data_table <- reactive({
        data_input_1() + data_input_2()
      })
      
      # render the table
      output$table <- renderDT({
        datatable(data_table())
      })
    }
  )
}

modFunctionUI <- function(id) {
  ns <- NS(id)
  
  selectInput(ns("var"), "Variable", choices = test$num)
  dataTableOutput(ns("table"))
}

ui <- fluidPage(
  modFunctionUI("table_1"),
  modFunctionUI("table_2"),
  modFunctionUI("table_3")
)

server <- function(input, output, session) {
  # call the modules for the editable tables and store the results
  amptable <- module1("table_1")
  refreshtable <- module2("table_2")
  
  # call the module for the table that takes inputs
  # the reactives musn't be evaluated
  module_add("table_3",
                data_input_1 = amptable,
                data_input_2 = refreshtable)
}

shinyApp(ui, server)

To me it seems a mistake to use reactiveValues , I would use a regular reactive.

The problem I get when I try using regular reactive is:

Warning: Error in <-: invalid (NULL) left side of assignment
[No stack trace available]

So the app runs fine but when I try to edit any of the cells within either table it crashes and produces the above error. I've added my updated code for reference:

module1 <- function(id) {
  moduleServer(
    id,
    function(input, output, session) {
      # initialise the reactive data object for the table
      #data <- reactiveValues(table = data_initialisation)
      data <- reactive(test[test$num == 1,])
      
      # render the table
      output$table <- renderDT({
        datatable(data(),
                  editable = TRUE)
      })
      
      # update the underlying data
      observeEvent(input$table_cell_edit, {
        data() <- editData(data(), input$table_cell_edit)
      })
      
      # return the data as a reactive
      return(reactive(data()))
    }
  )
}
library(shiny)
library(dplyr)
library(DT)

### Data----------------------------------------
set.seed(0)
x <- data.frame(num = rep(c(1:5),2))
test <- cbind(head(mtcars,10), x)

module1 <- function(id) {
  moduleServer(
    id,
    function(input, output, session) {
      # initialise the reactive data object for the table
      data <- reactive(list(table = test[test$num == req(input$var),]))
      
      # render the table
      output$table <- renderDT({

        datatable(data()$table,
                  editable = TRUE)
      })
      
      # update the underlying data
      observeEvent(input$table_cell_edit, {
      editData(data$table, input$table_cell_edit)
      })
      # return the data as a reactive
      return(reactive(data()$table))
    }
  )
}

module2 <- function(id) {
  moduleServer(
    id,
    function(input, output, session) {
      # initialise the reactive data object for the table
      data <- reactive(list(table = test[test$num == req({input$var}),]))
      
      # render the table
      output$table <- renderDT({
        datatable(data()$table,
                  editable = TRUE)
      })
      
      # update the underlying data
      observeEvent(input$table_cell_edit, {
    editData(data()$table, input$table_cell_edit)
      })
      
      # return the data as a reactive
      return(reactive(data()$table))
    }
  )
}

module_add <- function(id, data_input_1, data_input_2) {
  moduleServer(
    id,
    function(input, output, session) {
      # do the calculations
      data_table <- reactive({
        data_input_1() + data_input_2()
      })
      
      # render the table
      output$table <- renderDT({
        datatable(data_table())
      })
    }
  )
}

modFunctionUI <- function(id) {
  ns <- NS(id)
  
  tagList(selectInput(ns("var"), "Variable", choices = test$num),
  dataTableOutput(ns("table")))
}

ui <- fluidPage(
  modFunctionUI("table_1"),
  modFunctionUI("table_2"),
  modFunctionUI("table_3")
)

server <- function(input, output, session) {
  # call the modules for the editable tables and store the results
  amptable <- module1("table_1")
  refreshtable <- module2("table_2")
  
  # call the module for the table that takes inputs
  # the reactives musn't be evaluated
  module_add("table_3",
             data_input_1 = amptable,
             data_input_2 = refreshtable)
}

shinyApp(ui, server)
1 Like

Thanks for the feedback, this fixed the code!

Hi Nir,

I have a question regarding the utilization of input$var, is it possible to call upon an input$var from the main UI rather than within the module? For example, having a single selectInput in the main UI that I can call within the modules that I've made.

you would do that by passing the main ui input$var as a parameter that the module server code can accept. Wrap it in reactive({}) so that the module server code will react to its changes.

I'm running into an error:

Error in ==: comparison (1) is possible only for atomic and list types.

I'm guessing this is due to the module not reading the input$var as a numeric. I tried using as.numeric(choice), but this also came up with an error. In this case, is it a problem with calling data as a list?

module1 <- function(id, choice) {
  moduleServer(
    id,
    function(input, output, session) {
      # initialise the reactive data object for the table
      data <- reactive(list(table = test[test$num == choice,]))
      
      # render the table
      output$table <- renderDT({
        
        datatable(data()$table,
                  editable = TRUE)
      })
      
      # update the underlying data
      observeEvent(input$table_cell_edit, {
        editData(data$table, input$table_cell_edit)
      })
      # return the data as a reactive
      return(reactive(data()$table))
    }
  )
}

ui <- fluidPage(
  selectInput("var",
              "Variable",
              choices = test$num,
              selected = NULL),
  modFunctionUI("table_1"),
  modFunctionUI("table_2"),
  modFunctionUI("table_3")
)

server <- function(input, output, session) {
  # call the modules for the editable tables and store the results
  amptable <- module1("table_1", reactive({input$var}))
}

choice is a reactive so its not directly comparable, and needs to be dereferenced

module1 <- function(id, choice) {
  moduleServer(
    id,
    function(input, output, session) {
      # initialise the reactive data object for the table
      data <- reactive(list(table = test[test$num == choice(),]))
1 Like

Ah right, I forgot to call it as a reactive. Thank you so much for the help!