Cannot read input in nested Shiny module

I have two modules:

  • The inner module, which contains a text input and returns the its value in a reactive context, and
  • the outer module, which reads the output from the inner module and renders it as a text output.

The problem is that the inner module does not return the contents of the input. As far as I got, it has to do with the input object not being available inside the input variable.

Here is the most minimal example I could come up with where this is happening:

library(shiny)

inner_ui <- function(id) {
  ns <- NS(id)

  textInput(ns("inner_text"), "Type something")
}

inner <- function(input, output, session, id) {
  reactive(input$inner_text)
}

outer_ui <- function(id) {
  ns <- NS(id)

  tagList(
    inner_ui(ns("inner")),
    p("Preview"),
    textOutput(ns("outer_text"))
  )
}

outer <- function(input, output, session, id) {
  t <- callModule(inner, session$ns("inner"))
  output$outer_text <- renderText({ t() })

  t
}

ui <- fluidPage(
   outer_ui("outer")
)

server <- function(input, output) {

   res <- callModule(outer, "outer")

   observe({
     print(res())
   })
}

shinyApp(ui = ui, server = server)
#> PhantomJS not found. You can install it with webshot::install_phantomjs(). If it is installed, please make sure the phantomjs executable can be found via the PATH variable.

Shiny applications not supported in static R Markdown documents

Created on 2020-02-18 by the reprex package (v0.3.0)

Thanks in advance for any help you can provide :slight_smile:.

Hi @elias. The error was come from the namespace problem. In ui, the namespace is fine. The outer_ui will add the namespace outer-inner to the input$inner_text id. But in server, when callModule, all input and output will add the namespace automatically. So, in outer, the output$outer_text id is outer-outer_text, which is okay. But when you call inner in outer with session$ns("inner"), the namespace with automatic add outer and session$ns add outer again. The namespace for inner server will be outer-outer-inner. It will not match with the namespace of inner_text. So, just remove the session$ns in callModule for inner will be okay.

library(shiny)

inner_ui <- function(id) {
  ns <- NS(id)
  
  textInput(ns("inner_text"), "Type something")
}

inner <- function(input, output, session, id) {
  tmp <- reactive(input$inner_text)
  
  tmp
}

outer_ui <- function(id) {
  ns <- NS(id)

  
  tagList(
    inner_ui(ns("inner")),
    p("Preview"),
    textOutput(ns("outer_text"))
  )
}

outer <- function(input, output, session, id) {
  t <- callModule(inner, "inner")
  output$outer_text <- renderText({ t() })
  
  t
}

ui <- fluidPage(
  outer_ui("outer")
)

server <- function(input, output) {
  
  res <- callModule(outer, "outer")

  observe({
    print(res())
  })
}

shinyApp(ui = ui, server = server)
#> PhantomJS not found. You can install it with webshot::install_phantomjs(). If it is installed, please make sure the phantomjs executable can be found via the PATH variable.
3 Likes

Thanks a lot! It worked!

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.