Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stacks within modules #425

Open
JohnCoene opened this issue Sep 27, 2024 · 2 comments
Open

Stacks within modules #425

JohnCoene opened this issue Sep 27, 2024 · 2 comments
Labels
bug Something isn't working

Comments

@JohnCoene
Copy link
Member

JohnCoene commented Sep 27, 2024

We define stack names when creating the stack.

library(blockr)
library(shiny)

mod_ui <- function(id) {
  uiOutput(shiny::NS(id)("stack"))
}

mod_server <- function(id) {
  moduleServer(
    id,
    function(
      input,
      output,
      session
    ) {
      # "hello" or session$ns("hello") both fail
      stack <- new_stack(name = "hello")
      output$stack <- renderUI({
        generate_ui(stack)
      })
      generate_server(stack)
    }
  )
}

ui <- fluidPage(
  theme = bslib::bs_theme(5L),
  mod_ui("stack")
)

server <- function(input, output, session) {
  mod_server("stack")
}

shinyApp(ui, server)

The hack is to manually change the name attribute

stack <- new_stack(name = "hello")
generate_server(stack)
attr(stack, "name") <- session$ns("hello")
output$stack <- renderUI({
  generate_ui(stack)
})

EDIT: In the first example, the stack renders fine but underlying namespace is incorrect, none of the inputs of the stack work.

@JohnCoene JohnCoene added the bug Something isn't working label Sep 27, 2024
@DivadNojnarg
Copy link
Collaborator

We have an example in the doc, where you can pass custom id to generate_ui and generate_server.

library(blockr)
library(shiny)

mod_ui <- function(id) {
  uiOutput(shiny::NS(id)("stack"))
}

mod_server <- function(id) {
  moduleServer(
    id,
    function(
      input,
      output,
      session
    ) {
      # "hello" or session$ns("hello") both fail
      stack <- new_stack()
      output$stack <- renderUI({
        generate_ui(stack, id = session$ns("hello"))
      })
      generate_server(stack, id = "hello")
    }
  )
}

ui <- fluidPage(
  theme = bslib::bs_theme(5L),
  mod_ui("stack")
)

server <- function(input, output, session) {
  mod_server("stack")
}

shinyApp(ui, server)

If have to check why passing a name to stack fails in that case.

@DivadNojnarg
Copy link
Collaborator

DivadNojnarg commented Sep 27, 2024

When we call new_stack(name = session$ns("pouet")), we need the session since this is used on the UI side. On the server side, we don't need the namespace. This means there is an issue in the generate_server.stack function where we extract the id:

id <- coal(id, get_stack_name(x))

as get_stack_name(x) could contain the parent module namespace, which we don't want.

What we need is something like this in generate_server.stack, where we only remove the outer namespace:

id <- coal(id, tail(strsplit(get_stack_name(x), "-")[[1]], n = 1))

Example with one more level of parent module:

library(blockr)
library(shiny)

mod_inner_ui <- function(id) {
  uiOutput(shiny::NS(id)("stack"))
}

mod_inner_server <- function(id) {
  moduleServer(
    id,
    function(
      input,
      output,
      session
    ) {
      stack <- new_stack(name = session$ns("pouet"))
      output$stack <- renderUI({
        generate_ui(stack)
      })
      generate_server(stack)
    }
  )
}

mod_outer_ui <- function(id) {
  ns <- NS(id)
   mod_inner_ui(ns("inner"))
}

mod_outer_server <- function(id) {
  moduleServer(
    id,
    function(input, output, session) {
      mod_inner_server("inner")
    }
  )
}

ui <- fluidPage(
  theme = bslib::bs_theme(5L),
  mod_outer_ui("ext")
)

server <- function(input, output, session) {
  mod_outer_server("ext")
}

shinyApp(ui, server)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants