shinyshinyappsgolem

Why I cannot get my shiny app when adding golem framework?


Why I cannot get my shiny app when adding golem framework?

I am managing nevertheless to get my shiny elements without any golem framework:

Here is the shiny without golem:

library(shiny)

# Define the logo URL


ui <- fluidPage(
  tags$head(
    tags$style(HTML("
      body {
        display: flex;
        flex-direction: column;
        justify-content: flex-start;
        align-items: center;
        height: 100vh;
        margin: 5px 0;
        background-color: navy; /* Set background color for the body */
        position: relative; /* Add position relative for the logo */
      }
      .input-container {
        width: 100%;
        text-align: center;
        background-color: navy; /* Set background color for the input container */
        padding: 20px; /* Add padding for better visibility */
        width: 600px; /* Adjust the width of the input container */
      }
      .input-container input[type='text'],
      .input-container input[type='number'],
      .input-container .btn {
        width: 100%;
        padding: 15px;
        margin: 15px 0; /*increased from 5 to 15 for more space between inputs */
        box-sizing: border-box;
        font-size: 18px;
        text-align: center;
        color: navy; /* Text color navy */
        margin-bottom: 50px; /* larger space to next element */
      }
      .input-container .btn {
        margin-top: 20px;
        color: white;
      }
      /* Style for Your Details text */
      .details-container {
        text-align: center;
        width: 600px; /*larger inputs as desired */
        width: 100%;
      }
      .details-text {
        color: white;
        font-size: 24px;
        margin-bottom: 15px;
        text-align: center;
        display: inline-block;
      }
      ,form-group {
      margin-bottom: 50px; /* larger space to next element */
      }
      .shiny-input-container:not(.shiny-input-container-inline) {
      width: 600px; /*larger inputs as desired */
      max-width: 100%;
      }
      #nextButton, #nextButtonPage3 {
        width: 300px;   /* shorter than the other buttons */
        background-color: green; /* like in the screenshot */
        margin-top: 60px; /* larger space to above */
      }
      #notSureButton {
       width: 295px;   /* shorter than the other buttons */
       margin-top: 60px;   /* larger space to above */
      }
      #startButton {
        width: 300px; /* width of the start button, separately defined */
      }
       div#corner-triangle {
        display: block;
        width: 100px;
        height: 100px;
        border-style: solid;
        border-width: 200px 200px 0 0;
        border-color: #ffffff transparent transparent transparent;
        position: fixed;
        top: 0;
        left: 0;
        z-index: 99999;
        color: white;
        text-shadow: 0 0 25px 9px #fff;
       }
      .logo {
        position: absolute;
        bottom: 1px;
        left: 50%;
        transform: translateX(-50%);
        width: 300px; /* Adjust the width of the logo */
        height: auto; /* Maintain aspect ratio */
      }
    "))
  ),
  titlePanel(" "),
  uiOutput("page")
)

server <- function(input, output, session){
  output$page <- renderUI({
    if (is.null(input$currentPage)) {
      tagList(
        div(class = "input-container",
            actionButton("startButton", "Start", style = "font-size: 35px; color: navy;") #  style = "font-size: 24px;"
        ),
        tags$img(src = "www/free_english_logo.png", class = "logo", width = "400px") # Adjust the width of the logo
      )
    } else if (input$currentPage == "page2") {
      tagList(
        div(class = "input-container",
            tags$p(class = "details-text", "Your Details:"),
            textInput("name", label = NULL, placeholder = "Name", style = "background-color: lightblue; color: navy;"),
            textInput("nationality", label = NULL, placeholder = "Nationality", style = "background-color: lightyellow; color: navy;"),
            textInput("age", label = NULL, value = "", placeholder = "Age", style = "background-color: lightgreen; color: navy;"),
            textInput("email", label = NULL, placeholder = "Email", style = "background-color: lightgray; color: navy;"),
            actionButton("nextButton", "Next", style = "font-size: 30px; color: navy;") #  style = "font-size: 24px;"
        ),
        div(id = "corner-triangle",
            actionButton(label="Back", inputId = "bck1",
                         style = "top: -150px;
                                        left: 25px;
                                        font-size: 25px;
                                        position: relative;
                                        transform: rotate(-45deg);
                                        color: navy;
                                        border: none;
                                        background-color: transparent;
                                        font-weight: bold;
                                        padding: 2em;
                                        margin: -2em;
                                        outline: none;")),
        tags$img(src = "www/free_english_logo.png", class = "logo", width = "400px")
      )
    } else if (input$currentPage == "page3") {
      tagList(
        div(class = "input-container",
            tags$p(class = "details-text", "Teaching level:"),
            actionButton("basicButton", "Basic"),
            actionButton("intermediateButton", "Intermediate"),
            actionButton("intermediatePlusButton", "Intermediate +"),
            actionButton("notSureButton", "Not sure"),
            actionButton("nextButtonPage3", "Next", style = "font-size: 30px; color: navy;") #  style = "font-size: 24px;"
        ),
        div(id = "corner-triangle",
            actionButton(label="Back", inputId = "bck2",
                         style = "top: -150px;
                                        left: 25px;
                                        font-size: 25px;
                                        position: relative;
                                        transform: rotate(-45deg);
                                        color: navy;
                                        border: none;
                                        background-color: transparent;
                                        font-weight: bold;
                                        padding: 2em;
                                        margin: -2em;
                                        outline: none;")),
        tags$img(src ="www/free_english_logo.png", class = "logo", width = "400px")
      )
    }
  })

  observeEvent(input$startButton, {
    output$page <- renderUI({
      tagList(
        div(class = "input-container",
            tags$p(class = "details-text", "Your Details:"),
            textInput("name", label = NULL, placeholder = "Name"),
            textInput("nationality", label = NULL, placeholder = "Nationality"),
            textInput("age", label = NULL, value = "", placeholder = "Age"),
            textInput("email", label = NULL, placeholder = "Email"),
            actionButton("nextButton", "Next", style = "font-size: 30px; color: navy;")
        ),
        div(id = "corner-triangle",
            actionButton(label="Back", inputId = "bck2",
                         style = "top: -150px;
                                        left: 25px;
                                        font-size: 25px;
                                        position: relative;
                                        transform: rotate(-45deg);
                                        color: navy;
                                        border: none;
                                        background-color: transparent;
                                        font-weight: bold;
                                        padding: 2em;
                                        margin: -2em;
                                        outline: none;")),
        tags$img(src = "www/free_english_logo.png", width = "400px")
      )
    })
  })

  observeEvent(input$nextButton, {
    name <- input$name
    nationality <- input$nationality
    age <- input$age
    email <- input$email

    output$page <- renderUI({
      tagList(
        div(class = "input-container",
            tags$p(class = "details-text", "Teaching level:"),
            actionButton("basicButton", "Basic", style = "background-color: lightblue; color: navy;"),
            actionButton("intermediateButton", "Intermediate", style = "background-color: lightyellow; color: navy;"),
            actionButton("intermediatePlusButton", "Intermediate +", style = "background-color: lightgreen; color: navy;"),
            actionButton("notSureButton", "Not sure", style = "background-color: lightgray; color: navy;"),
            actionButton("nextButtonPage3", "Next", style = "font-size: 30px; color: navy;") #
        ),
        div(id = "corner-triangle",
            actionButton(label="Back", inputId = "bck2",
                         style = "top: -150px;
                                        left: 25px;
                                        font-size: 25px;
                                        position: relative;
                                        transform: rotate(-45deg);
                                        color: navy;
                                        border: none;
                                        background-color: transparent;
                                        font-weight: bold;
                                        padding: 2em;
                                        margin: -2em;
                                        outline: none;")),
        tags$img(src = "www/free_english_logo.png", class = "logo", width = "400px")
      )
    })
  })
  observeEvent(input$bck1, {
    output$page <- renderUI({
      tagList(
        div(
          class = "input-container",
          actionButton("startButton", "Start", style = "font-size: 35px; color: navy;")
        ),
        tags$img(
          src = "www/free_english_logo.png",
          class = "logo",
          width = "400px"
        ) # Adjust the width of the logo
      )
    })
  })

  observeEvent(input$bck2, {
    output$page <- renderUI({
      tagList(
        div(class = "input-container",
            tags$p(class = "details-text", "Your Details:"),
            textInput("name", label = NULL, placeholder = "Name"),
            textInput("nationality", label = NULL, placeholder = "Nationality"),
            textInput("age", label = NULL, value = "", placeholder = "Age"),
            textInput("email", label = NULL, placeholder = "Email"),
            actionButton("nextButton", "Next", style = "font-size: 24px; color: navy;")
        ),
        div(id = "corner-triangle",
            actionButton(label="Back", inputId = "bck1",
                         style = "top: -150px;
                                        left: 25px;
                                        font-size: 25px;
                                        position: relative;
                                        transform: rotate(-45deg);
                                        color: navy;
                                        border: none;
                                        background-color: transparent;
                                        font-weight: bold;
                                        padding: 2em;
                                        margin: -2em;
                                        outline: none;")),
        tags$img(src = "app/www/free_english_logo.png", class = "logo", width = "400px") # Adjust the width of the logo
      )
    })
  })
}
shinyApp(ui,server)

the above code works if you run it independently of golem.

Now, if I am adding ui and server with the golem framework does not work.

This is what I am doing:

#' mod_first_page_ui UI Function
#'
#' @description A shiny Module.
#'
#' @param id,input,output,session Internal parameters for {shiny}.
#'
#' @noRd
#'
#' @importFrom shiny NS tagList
mod_first_page_ui <- function(id){
  ns <- NS(id)
  tagList(
    fluidPage(tags$head(
      tags$link(rel = "stylesheet", type = "text/css", href = "fec/inst/app/www/styles.css")
    ),
    titlePanel(" "),
    uiOutput("page"))
  )
}

#' mod_first_page_server Server Functions
#'
#' @noRd
mod_first_page_server <- function(id_fec){
  moduleServer(id_fec, function(input, output, session){
    output$page <- renderUI({
      if (is.null(input$currentPage)) {
        tagList(
          div(class = "input-container",
              actionButton(ns("startButton"), "Start", style = "font-size: 35px; color: navy;") #  style = "font-size: 24px;"
          ),
          tags$img(src = "www/free_english_logo.png", class = "logo", width = "400px") # Adjust the width of the logo
        )
      } else if (input$currentPage == "page2") {
        tagList(
          div(class = "input-container",
              tags$p(class = "details-text", "Your Details:"),
              textInput("name", label = NULL, placeholder = "Name", style = "background-color: lightblue; color: navy;"),
              textInput("nationality", label = NULL, placeholder = "Nationality", style = "background-color: lightyellow; color: navy;"),
              textInput("age", label = NULL, value = "", placeholder = "Age", style = "background-color: lightgreen; color: navy;"),
              textInput("email", label = NULL, placeholder = "Email", style = "background-color: lightgray; color: navy;"),
              actionButton("nextButton", "Next", style = "font-size: 30px; color: navy;") #  style = "font-size: 24px;"
          ),
          div(id = "corner-triangle",
              actionButton(label="Back", inputId = "bck1",
                           style = "top: -150px;
                                        left: 25px;
                                        font-size: 25px;
                                        position: relative;
                                        transform: rotate(-45deg);
                                        color: navy;
                                        border: none;
                                        background-color: transparent;
                                        font-weight: bold;
                                        padding: 2em;
                                        margin: -2em;
                                        outline: none;")),
          tags$img(src = "www/free_english_logo.png", class = "logo", width = "400px")
        )
      } else if (input$currentPage == "page3") {
        tagList(
          div(class = "input-container",
              tags$p(class = "details-text", "Teaching level:"),
              actionButton("basicButton", "Basic"),
              actionButton("intermediateButton", "Intermediate"),
              actionButton("intermediatePlusButton", "Intermediate +"),
              actionButton("notSureButton", "Not sure"),
              actionButton("nextButtonPage3", "Next", style = "font-size: 30px; color: navy;") #  style = "font-size: 24px;"
          ),
          div(id = "corner-triangle",
              actionButton(label="Back", inputId = "bck2",
                           style = "top: -150px;
                                        left: 25px;
                                        font-size: 25px;
                                        position: relative;
                                        transform: rotate(-45deg);
                                        color: navy;
                                        border: none;
                                        background-color: transparent;
                                        font-weight: bold;
                                        padding: 2em;
                                        margin: -2em;
                                        outline: none;")),
          tags$img(src ="www/free_english_logo.png", class = "logo", width = "400px")
        )
      }
    })

    observeEvent(input$startButton, {
      output$page <- renderUI({
        tagList(
          div(class = "input-container",
              tags$p(class = "details-text", "Your Details:"),
              textInput("name", label = NULL, placeholder = "Name"),
              textInput("nationality", label = NULL, placeholder = "Nationality"),
              textInput("age", label = NULL, value = "", placeholder = "Age"),
              textInput("email", label = NULL, placeholder = "Email"),
              actionButton("nextButton", "Next", style = "font-size: 30px; color: navy;")
          ),
          div(id = "corner-triangle",
              actionButton(label="Back", inputId = "bck2",
                           style = "top: -150px;
                                        left: 25px;
                                        font-size: 25px;
                                        position: relative;
                                        transform: rotate(-45deg);
                                        color: navy;
                                        border: none;
                                        background-color: transparent;
                                        font-weight: bold;
                                        padding: 2em;
                                        margin: -2em;
                                        outline: none;")),
          tags$img(src = "www/free_english_logo.png", class = "logo", width = "400px")
        )
      })
    })

    observeEvent(input$nextButton, {
      name <- input$name
      nationality <- input$nationality
      age <- input$age
      email <- input$email

      output$page <- renderUI({
        tagList(
          div(class = "input-container",
              tags$p(class = "details-text", "Teaching level:"),
              actionButton("basicButton", "Basic", style = "background-color: lightblue; color: navy;"),
              actionButton("intermediateButton", "Intermediate", style = "background-color: lightyellow; color: navy;"),
              actionButton("intermediatePlusButton", "Intermediate +", style = "background-color: lightgreen; color: navy;"),
              actionButton("notSureButton", "Not sure", style = "background-color: lightgray; color: navy;"),
              actionButton("nextButtonPage3", "Next", style = "font-size: 30px; color: navy;") #
          ),
          div(id = "corner-triangle",
              actionButton(label="Back", inputId = "bck2",
                           style = "top: -150px;
                                        left: 25px;
                                        font-size: 25px;
                                        position: relative;
                                        transform: rotate(-45deg);
                                        color: navy;
                                        border: none;
                                        background-color: transparent;
                                        font-weight: bold;
                                        padding: 2em;
                                        margin: -2em;
                                        outline: none;")),
          tags$img(src = "www/free_english_logo.png", class = "logo", width = "400px")
        )
      })
    })
    observeEvent(input$bck1, {
      output$page <- renderUI({
        tagList(
          div(
            class = "input-container",
            actionButton("startButton", "Start", style = "font-size: 35px; color: navy;")
          ),
          tags$img(
            src = "www/free_english_logo.png",
            class = "logo",
            width = "400px"
          ) # Adjust the width of the logo
        )
      })
    })

    observeEvent(input$bck2, {
      output$page <- renderUI({
        tagList(
          div(class = "input-container",
              tags$p(class = "details-text", "Your Details:"),
              textInput("name", label = NULL, placeholder = "Name"),
              textInput("nationality", label = NULL, placeholder = "Nationality"),
              textInput("age", label = NULL, value = "", placeholder = "Age"),
              textInput("email", label = NULL, placeholder = "Email"),
              actionButton("nextButton", "Next", style = "font-size: 24px; color: navy;")
          ),
          div(id = "corner-triangle",
              actionButton(label="Back", inputId = "bck1",
                           style = "top: -150px;
                                        left: 25px;
                                        font-size: 25px;
                                        position: relative;
                                        transform: rotate(-45deg);
                                        color: navy;
                                        border: none;
                                        background-color: transparent;
                                        font-weight: bold;
                                        padding: 2em;
                                        margin: -2em;
                                        outline: none;")),
          tags$img(src = "www/free_english_logo.png", class = "logo", width = "400px") # Adjust the width of the logo
        )
      })
    })
  })
}

this is how my app_server file looks like:

#' The application server-side
#'
#' @param input,output,session Internal parameters for {shiny}.
#'     DO NOT REMOVE.
#' @import shiny
#' @noRd
app_server <- function(input, output, session) {

  # Load the modules
  # callModule(mod_first_page_server_1, "id_fec")
  mod_first_page_server("mod_first_page")
}

And this is how my app_ui looks like:

#' The application User-Interface
#'
#' @param request Internal parameter for `{shiny}`.
#'     DO NOT REMOVE.
#' @import shiny
#' @noRd
app_ui <- function(request) {
  tagList(
    golem_add_external_resources(),
    mod_first_page_ui("mod_first_page_1")

  )
}


#' Add external Resources to the Application
#'
#' This function is internally used to add external
#' resources inside the Shiny application.
#'
#' @import shiny
#' @importFrom golem add_resource_path activate_js favicon bundle_resources
#' @noRd
golem_add_external_resources <- function() {
  add_resource_path(
    "www",
    app_sys("app/www")
  )

  tags$head(
    favicon(),
    bundle_resources(
      path = app_sys("app/www"),
      app_title = "fec"
    )
    # Add here other external resources
    # for example, you can add shinyalert::useShinyalert()
  )
}

And GitHub link for this project is here:

Github Link - press here


Solution

  • I added a pull request here.

    1. The module UI and server should have the same id, otherwise they cannot communicate with each other.
    2. Modules are using isolated namespacing, therefore all input ids should be wrapped within ns(). This is a design choice of shiny modules: the inputs will be prefixed with the server id, ensuring that they will be unique in the entire app. Since you are also declaring inputs in the server, you have to declare ns <- session$ns in the module server function for it to work.

    There are other problems with the app such as code duplication and the fact that you are overwriting the entire page every time, but the changes mentioned above should at least get you started. Good luck!