Willem
Willem

Reputation: 1124

How to use callModule from within another module? (Can I use the same id?)

I'm trying to use callModule from within another module (server side). However, when using callModule I need to provide an id argument. I would like to be able to pass the same id provided to outerModule on to each inner module.

In other words, is there a way to access the id a module was called with, from within the module?

library(shiny)

innerModule1 <- function(input, output, session, someReactiveInput){

  table <- reactive({
    table <- someCode(someReactiveInput())
  })

  return(table)

}

innerModule2 <- function(input, output, session, someOtherReactiveInput){

  table <- reactive({
    table <- someOtherCode(someOtherReactiveInput())
  })

  return(table)

}

outerModule <- function(input, output, session, someReactiveInput, someOtherReactiveInput){

  table <- reactive({

    table1 <- callModule(
      innerModule1,
      id = "hardcodedID",   # I want to use the same id as the one provided to outerModule
      someReactiveInput
    )

    table2 <- callModule(
      innerModule2,
      id = "hardcodedID",   # I want to use the same id as the one provided to outerModule
      someOtherReactiveInput
    )

    table <- someMoreCode(table1(), table2())

  })

  # More code follows here, but let's keep it simple for now

}

ui <- navbarPage( # Some inputs which are not relevant here I think )

server <- function(input, output, session){

  table_A <- callModule(
    outerModule,
    id = "A",
    someReactiveInput_A,
    someOtherReactiveInput_A
  )

  table_B <- callModule(
    outerModule,
    id = "B",
    someReactiveInput_B,
    someOtherReactiveInput_B
  )

  # More code

}

I am aware that an alternative would be to pass both tables as inputs to outerModule. However, that would require me to use callModule on both of my inner modules directly inside the server function. This would create more code duplication (I would have to do it twice, once for each id), and would make my already very long server function even longer...

Upvotes: 0

Views: 634

Answers (1)

shosaco
shosaco

Reputation: 6165

You can get the ID inside the module with the ns function:

session$ns("")

yields "ORIGINAL_ID-". Removing the - gives your desired ID, that is, you are looking for

sub("-", "", session$ns(""))

You minimal example was not runnable, see the example below.

library(shiny)

innerModule1 <- function(input, output, session, someReactiveInput){

  table <- reactive({
    return(data.frame(col1 = someReactiveInput()))
  })

  return(table)

}

innerModule2 <- function(input, output, session, someOtherReactiveInput){

  table <- reactive({
    return(data.frame(col1 = someOtherReactiveInput()))
  })

  return(table)

}

outerModule <- function(input, output, session, someReactiveInput, someOtherReactiveInput){

  table <- reactive({

    table1 <- callModule(
      innerModule1,
      id = sub("-", "", session$ns("")),
      someReactiveInput
    )

    table2 <- callModule(
      innerModule2,
      id = sub("-", "", session$ns("")),
      someOtherReactiveInput
    )

    return(rbind(table1(), table2()))

  })

  return(table)

}

ui <- fluidPage(title="",
                 numericInput("inputA1", "Input 1", value =1),
                 numericInput("inputA2", "Input 2", value =2),
                 tableOutput("table_A"),
                 tableOutput("table_B"))

  server <- function(input, output, session){

    table_A <- callModule(
      outerModule,
      id = "A",
      reactive({ input$inputA1 }),
      reactive({ input$inputA2 })
    )

    output$table_A <- renderTable({
      data.frame(a=table_A())
    })

    table_B <- callModule(
      outerModule,
      id = "B",
      reactive({ input$inputA1 }),
      reactive({ input$inputA2 })
    )

    output$table_B <- renderTable({
      data.frame(a=table_B())
    })

  }

  shinyApp(ui,server)

Upvotes: 3

Related Questions