Assuming I have 2 action buttons as a starting page 'Client' & 'Employee' as shown below, and for each option, there is a different web application.
when the user clicks the 'Client' button I need the following code to be run:
library(shiny)
ui <-
navbarPage(
"The Client Web",
tabPanel("Section1 "),
tabPanel(" Section1 2")
)
server <- function(input, output,session){
}
shinyApp(ui = ui, server = server)
and when the user clicks the 'Employee' button I need the following code to be run:
library(shiny)
ui <-
navbarPage(
"The Employee Web",
tabPanel("Component 1"),
tabPanel("Component 2"),
tabPanel("Component 3")
)
server <- function(input, output,session){
}
shinyApp(ui = ui, server = server)
I need both of the web applications in one app depending on the type of the user either 'Client' or 'Employee'. Thank you in advance!
Using JavaScript
I would do it using Javascript code to hide/show either of the pages.
You have to create your app with de buttons and both navbarpages.
library(shiny)
ui <- fluidPage(
# Buttons
actionButton('clientsBtn', 'Clients'),
actionButton('employeeBtn', 'Employee'),
# Employee pag
div(
class = 'employees-page',
navbarPage(
"The Employee Web",
tabPanel("Component 1"),
tabPanel("Component 2"),
tabPanel("Component 3")
)
),
# Clients page
div(
class = 'clients-page',
navbarPage(
"The Client Web",
tabPanel("Section1 "),
tabPanel(" Section1 2")
)
),
# Javascript to control de page logic
includeScript('script.js')
)
server <- function(input, output,session){
}
shinyApp(ui = ui, server = server)
The script.js file is just a text file with that extension.
// hide by default the clients page
$('.clients-page').hide();
$('#clientsBtn').on('click', () => {
$('.employees-page').hide();
$('.clients-page').show();
})
$('#employeeBtn').on('click', ()=>{
$('.employees-page').show();
$('.clients-page').hide();
})
Individual pages using shiny.router
As I promised, here is the approach using {shiny.router} to accomplish what you want.
library(shiny)
library(shiny.router)
# The root page is separated from clients and employee pages
# and contains two buttons/links that takes you the destination
# you wish
root_page <- tagList(
tags$a(
div(class='btn btn-default', id='clientsBtn', 'Clients'),
href=route_link('clients')
),
tags$a(
div(class='btn btn-default', id='employeeBtn', 'Employee'),
href=route_link('employees')
)
)
# The employee and clients page should include a button/link
# to take you back to the root page. I place the button in the
# first tabpanel of each page, but for better ux is good idea
# if you place it in all of them. Consider change its style and
# position using css configuration.
employee_page <- tagList(
navbarPage(
"The Employee Web",
tabPanel(
"Component 1",
tags$a(
div(class='btn btn-default', id='home1', 'Home'),
href=route_link('/')
)
),
tabPanel("Component 2"),
tabPanel("Component 3")
)
)
clients_page <- tagList(
navbarPage(
"The Client Web",
tabPanel(
"Section1 ",
tags$a(
div(class='btn btn-default', id='home1', 'Home'),
href=route_link('/')
)
),
tabPanel(" Section1 2")
)
)
router <- make_router(
route("/", root_page),
route("employees", employee_page),
route("clients", clients_page)
)
ui <- fluidPage(
router$ui
)
server <- function(input, output, session) {
router$server(input, output, session)
}
shinyApp(ui, server)
I got theses result:
when I have tried the following code:
library(shiny)
library(shiny.router)
Cleints_page <- div(
titlePanel("Cleints"),
p("This is the Cleints web app")
)
Employees_page <- div(
titlePanel("Employees"),
p("This is the Employees web app")
)
router <- make_router(
route("/", Cleints_page),
route("employees", Employees_page)
)
ui <- fluidPage(
tags$ul(
tags$li(a(href = route_link("/"), "Cleints
Web")),
tags$li(a(href = route_link("employees"),
"Employees Web"))
),
router$ui
)
server <- function(input, output, session) {
router$server(input, output, session)
}
shinyApp(ui, server)
but still, I need each one of them to be a separate page. How I can achieve that?
Related
When I run the app, I want the tab 2 to be clicked, so I can see it first, not tab 1. How can I do so ?
# USER INTERFACE
ui <- fluidPage(
mainPanel(
tabsetPanel(
tabPanel("tab 1"),
tabPanel("tab 2"),
)
)
)
# SERVER
server <- function(input, output) {
}
shinyApp(ui = ui, server = server)
Try:
tabSetPanel(tabPanel("tab1"), tabPanel("tab2"), selected="tab2")
I want to jump to a certain page of an embedded PDF in shiny. I use tags$iframe to display the PDF. I know that I have to expand the URL in tags$iframe to jump to a certain page of the PDF by adding #page=x, i.e. tags$iframe(style="height:785px; width:100%", src="http://www.pdf995.com/samples/pdf.pdf#page=3").
However, if I have multiple tabs and switch from tab 1 to tab 2 and back to tab 1, the PDF always shows page 1. I could reload the whole tab/PDF to jump back to page 3, but I don't want to do that!
I tried to use JavaScript but it doesn't work because document.getElementById doesn't work properly.
My code so far
library(shiny)
library(shinyjs)
ui <- tagList(
useShinyjs(),
tags$script('Shiny.addCustomMessageHandler("go_to_page", function(message) {
document.getElementById("show_pdf").contentWindow.PDFViewerApplication.page = 3;
});'),
fluidPage(
fluidRow(
column(6,
tabsetPanel(id = "tabs",
tabPanel(
"Tab 1",
uiOutput("show_pdf")
),
tabPanel(
"Tab 2",
uiOutput("show_pdf1"))
)
)
))
)
server <- function(input, output, session){
output$show_pdf <- renderUI({
tags$iframe(style="height:785px; width:100%", src="http://www.pdf995.com/samples/pdf.pdf#page=3")
})
output$show_pdf1 <- renderUI({
tags$iframe(style="height:785px; width:100%", src="http://www.pdf995.com/samples/pdf.pdf#page=4")
})
observe({
input$tabs
session$sendCustomMessage(type = 'go_to_page', message = runif(1))
})
}
shinyApp(ui = ui, server = server)
What do I have to change so that the code works properly?
Is there some way to have a dynamic titlePanel title that pulls directly from UI kind of like below? If it's not possible, is it possible to have a second row that's similar to titlepanel right below titlepanel?
# Define UI ----
ui <- fluidPage(
##Whatever UI code here
titlepanel_text = paste0("Some string", variable_with_text)
)
# Define server logic ----
server <- function(input, output) {
titlePanel("title panel"),
#Rest of server code here
}
Render the text in the server and grab the text output in the UI:
library(shiny)
# Define UI ----
ui <- fluidPage(
##Whatever UI code here
titlePanel(textOutput("title_panel")),
sidebarLayout(
sidebarPanel(),
mainPanel(h1("text"))
)
)
# Define server logic ----
server <- function(input, output) {
output$title_panel <- renderText({
paste0("This is the date/time: ", Sys.time() )
})
}
shiny::shinyApp(ui, server)
you can insert this kind of code to structure your title panel
# Application title
titlePanel(
fixedRow(
column(9,
"My Template",
fixedRow(
column(9,
paste0("Author : ", author)
),
column(3,
paste0("date : ", today(tzone = ""))
)
)
)
) ),
I am trying to build an app where the user is able to switch tabs when clicking on a specific object. However, I have developed the app using modules and would like to continue to do so. I am running into a problem with the scoping when trying to call the updateNavbarPage() function from inside of the modules. I have created a MWE example to illustrate the problem.
#==================================================
# MRE for updateNavBar scoping issue within modules
#==================================================
modOneUI <- function(id){
ns <- NS(id)
tagList(
h4(
"Click this button to change tabs!"
),
actionButton(
ns("submit"),
label = "Go to next Tab"
)
)
}
modOne <- function(input, output, session){
observeEvent(input$submit, {
updateNavbarPage(session, "nav-page", "tab2")
})
}
ui <- shinyUI(
navbarPage(
id = "nav-page",
title = "Example Navbar Page Issue",
tabPanel(
id = "tab1",
value = "tab1",
div(
"Tab 1"
),
div(
modOneUI("tab1_mod")
)
),
tabPanel(
id = "tab2",
value = "tab2",
div(
"Tab 2"
),
div(
h4("This is the second tab")
)
)
)
)
server <- shinyServer(function(input, output, session){
callModule(modOne, "tab1_mod")
})
shinyApp(ui = ui, server = server)
When this app is run, and the action button is clicked on the first tab, nothing happens. However if you remove the module and place the ui and server module code directly into the ui and server portions then clicking the button works. Here is the code with the modules removed.
ui <- shinyUI(
navbarPage(
id = "nav-page",
title = "Example Navbar Page Issue",
tabPanel(
id = "tab1",
value = "tab1",
div(
"Tab 1"
),
div(
h4(
"Click this button to change tabs!"
),
actionButton(
"submit",
label = "Go to next Tab"
)
)
),
tabPanel(
id = "tab2",
value = "tab2",
div(
"Tab 2"
),
div(
h4("This is the second tab")
)
)
)
)
server <- shinyServer(function(input, output, session){
observeEvent(input$submit, {
updateNavbarPage(session, "nav-page", "tab2")
})
})
shinyApp(ui = ui, server = server)
Is there any way to use updateNavbarPage() from within a module to switch to a tab that is in not in the module?
Do not ask me why :-) but it works like this:
modOne <- function(input, output, session, x){
observeEvent(input$submit, {
updateNavbarPage(x, "nav-page", "tab2")
})
}
callModule(modOne, "tab1_mod", x=session)
I setup the UI in server.R for more control, but shinyDashboard does not work when defined in server.R.
I use this method with navBarPage without problems.
This code works
library(shiny)
library(shinydashboard)
ui <- dashboardPage( dashboardHeader( ),
dashboardSidebar(),
dashboardBody() )
server <- shinyServer(function(input, output) { })
runApp(list(ui= ui, server = server))
But this one just show an empty page
ui <- uiOutput('dash')
server <- shinyServer(function(input, output) {
output$dash <- renderUI({
dashboardPage(dashboardHeader( ),
dashboardSidebar(),
dashboardBody() )
})
})
runApp(list(ui= ui, server = server))
This is an example using navBarPage, that works fine
ui <- uiOutput('nav')
server <- shinyServer(function(input, output) {
output$nav <- renderUI({
navbarPage("App Title",
tabPanel("Tab 1"),
tabPanel("Tab 2") )
})
})
runApp(list(ui= ui, server = server))
I don't think that you can use only a uiOutput to create a dashboard. I'm assuming that your goal is to create a dynamic dashboard. For that you need to define the header, body and side bar in your UI and use functions such as renderMenu on SERVER to create it. Here is an example to create a dashboard with all the UI defined in the SERVER.
ui <- dashboardPage(
dashboardHeader(title = "My Page"),
dashboardSidebar(sidebarMenuOutput("sideBar_menu_UI")),
dashboardBody(
uiOutput("body_UI"),
uiOutput("test_UI")
)
)
server <- shinyServer(function(input, output, session) {
output$sideBar_menu_UI <- renderMenu({
sidebarMenu(id = "sideBar_Menu",
menuItem("Menu 1", tabName="menu1_tab", icon = icon("calendar")),
menuItem("Menu 2", tabName="menu2_tab", icon = icon("database"))
)
})
output$test_UI <- renderUI ({
tabItems(
tabItem(tabName = "menu1_tab", uiOutput("menu1_UI")),
tabItem(tabName = "menu2_tab", uiOutput("menu2_UI"))
)
})
output$body_UI <- renderUI ({
p("Default content in body outsite any sidebar menus.")
})
output$menu1_UI <- renderUI ({
box("Menu 1 Content")
})
output$menu2_UI <- renderUI ({
box("Menu 2 Content")
})
})
runApp(list(ui= ui, server = server))
In this example, a menu for the sidebar is not selected by default and the content of body_UI will be visible all the time. If you want that your dashboard starts on a specific menu, put the sidebarMenu in your UI. Also you can delete the body_UI.