I am writing a shiny app where I have a sidebarPanel containing various interactive user elements. This sidebarPanel is embedded in the ui in such a way:
Server/UI
library(shiny)
ui <- navbarPage(
title="some title",
tabPanel(
title="Tab 1",
sidebarLayout(
# This is the element I want to reuse, see second tabPanel
sidebarPanel(radioButtons(inputId="button1", label="Choose", choices=c("1", "2"))),
mainPanel(uiOutput("output1"))
)
),
tabPanel(
title="Tab 2",
sidebarLayout(
sidebarPanel(radioButtons(inputId="button1", label="Choose", choices=c("1", "2"))),
mainPanel(uiOutput("output2"))
)
)
)
server <- function(input, output, session) {
output$output1 <- renderText("Text 1")
output$output2 <- renderText("Text 2")
}
shinyApp(ui=ui, server=server)
I have tried creating a module such as they did in Translate shiny app using shiny.i18n in modules?
Module module.R
library(shiny)
samplePanel <- function(id) {
ns <- NS(id)
sidebarPanel(
radioButtons(inputId="button1", label="Choose", choices=c("1", "2")),
textOutput("sample_text")
)
}
sampleModule <- function(input, output, session) {
output$sample_text <- "Sample text"
}
New Server/UI main script
source("module.R")
library(shiny)
ui <- navbarPage(
title="some title",
tabPanel(
title="Tab 1",
sidebarLayout(
samplePanel("moduleId"),
mainPanel(uiOutput("output1"))
)
),
tabPanel(
title="Tab 2",
sidebarLayout(
samplePanel("moduleId"),
mainPanel(uiOutput("output2"))
)
)
)
server <- function(input, output, session) {
callModule(sampleModule, "moduleId")
output$output1 <- renderText("Text 1")
output$output2 <- renderText("Text 2")
}
shinyApp(ui=ui, server=server)
What is it I don't understand about modularizing shiny code? One thing that surprises me is that my samplePanel
doesn't even show the sample_text
I want it to show.
Does this give you something close to what you want?
library(shiny)
samplePanel <- function(id) {
ns <- NS(id)
sidebarPanel(
radioButtons(inputId=ns("button1"), label="Choose", choices=c("1", "2")),
textOutput(ns("sample_text"))
)
}
sampleModule <- function(input, output, session) {
output$sample_text <- renderText("Sample text")
}
ui <- navbarPage(
title="some title",
tabPanel(
title="Tab 1",
sidebarLayout(
samplePanel("moduleId1"),
mainPanel(uiOutput("output1"))
)
),
tabPanel(
title="Tab 2",
sidebarLayout(
samplePanel("moduleId2"),
mainPanel(uiOutput("output2"))
)
)
)
server <- function(input, output, session) {
callModule(sampleModule, "moduleId1")
callModule(sampleModule, "moduleId2")
output$output1 <- renderText("Text 1")
output$output2 <- renderText("Text 2")
}
shinyApp(ui=ui, server=server)
In response to discussion in comments, this layout moves the module from the tabPanel
sidebar to the page sidebar, meaning that a single instance is common to each of the tabPanel
s. As there's now only a single instance, there may not be any need to use a module.
library(shiny)
samplePanel <- function(id) {
ns <- NS(id)
sidebarPanel(
radioButtons(inputId=ns("button1"), label="Choose", choices=c("1", "2")),
textOutput(ns("sample_text"))
)
}
sampleModule <- function(input, output, session) {
output$sample_text <- renderText("Sample text")
}
ui <- navbarPage(
title="some title",
samplePanel("moduleId1"),
mainPanel(
tabsetPanel(
tabPanel(
title="Tab 1",
uiOutput("output1")
),
tabPanel(
title="Tab 2",
uiOutput("output2")
)
)
)
)
server <- function(input, output, session) {
callModule(sampleModule, "moduleId1")
output$output1 <- renderText("Text 1")
output$output2 <- renderText("Text 2")
}
shinyApp(ui=ui, server=server)