I am trying to get a global search field into my navbarPage
after some tabPanel
. I am not sure if it is possible, since all my tests producing the
You can do this by manipulating the navbar HTML a little bit. Valter is correct - you can achieve this by constructing the menu entirely in HTML instead of using Shiny. But there's an easier way: you can build the navbar in regular Shiny, and then use htmltools
to slightly modify it. Here's one quick solution that I think is the cleanest out of the current proposed solutions:
library(shiny)
navbarPageWithInputs <- function(..., inputs) {
navbar <- navbarPage(...)
form <- tags$form(class = "navbar-form", inputs)
navbar[[3]][[1]]$children[[1]] <- htmltools::tagAppendChild(
navbar[[3]][[1]]$children[[1]], form)
navbar
}
ui <- navbarPageWithInputs(
"Test app",
tabPanel("tab1", "tab 1", textOutput("out")),
tabPanel("tab2", "tab 2"),
inputs = textInput("search", NULL, placeholder = "Search")
)
server <- function(input, output, session) {
output$out <- renderText(input$search)
}
shinyApp(ui = ui, server = server)
Basically I created a navbarPageWithInputs()
function that accepts all the same parameters as navbarPage()
, and also an inputs
parameter. All this function does is call the regular navbarPage()
, and then adds the given inputs to the HTML.
This is one possible way, to reconstruct the menu with HTML. It does not look very clean but it does what you are looking for.
app.R
library(shiny)
ui <- shinyUI(
tagList(
bootstrapPage(
HTML('
<nav class="navbar navbar-default" role="navigation">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Old Faithful Geyser Data</a>
</div>
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li class="active"><a href="#plot1" data-toggle="tab" data-value="Plot1">First</a></li>
<li><a href="#plot2" data-toggle="tab" data-value="Plot2">Second</a></li>
</ul>
<div class="col-sm-3 col-md-3">
<form class="navbar-form" role="search">
<div class="input-group">
<input id="searchBox" type="text" class="form-control" placeholder="Search" name="q">
</div>
</form>
</div>
</div><!-- /.navbar-collapse -->
</nav>
'),
tags$div(class="container-fluid",
tags$div(class="tab-content",
HTML('<div class="tab-pane active" data-value="Plot1" id="plot1">'),
sliderInput("bins1",
"Number of bins:",
min = 1,
max = 50,
value = 30),
plotOutput("distPlot1"),
verbatimTextOutput("searchBoxValuePlot1"),
HTML('</div>'),
HTML('<div class="tab-pane" data-value="Plot2" id="plot2">'),
sliderInput("bins2",
"Number of bins:",
min = 1,
max = 50,
value = 30),
plotOutput("distPlot2"),
verbatimTextOutput("searchBoxValuePlot2"),
HTML('</div>')
)
)
)
))
server <- function(input, output, session) {
output$distPlot1 <- renderPlot({
# generate bins based on input$bins from ui.R
x <- faithful[, 2]
bins <- seq(min(x), max(x), length.out = input$bins1 + 1)
# draw the histogram with the specified number of bins
hist(x, breaks = bins, col = 'darkgray', border = 'white')
})
output$distPlot2 <- renderPlot({
# generate bins based on input$bins from ui.R
x <- faithful[, 1]
bins <- seq(min(x), max(x), length.out = input$bins2 + 1)
# draw the histogram with the specified number of bins
hist(x, breaks = bins, col = 'darkgray', border = 'white')
})
searchBoxValue <- reactive({
input$searchBox
})
output$searchBoxValuePlot1 <- renderPrint({
paste("You entered: ", searchBoxValue(), "and you are on the first link", sep = " ")
})
output$searchBoxValuePlot2 <- renderPrint({
paste("You entered: ", searchBoxValue(), "and you are on the second link", sep = " ")
})
}
shinyApp(ui, server)
In base Shiny you can do it using a tabPanel
, if the re-rendering of current tabPanel is not to costly:
ui <- navbarPage('test',id='test',
tabPanel('my app1',
titlePanel("Old Faithful Geyser Data1"),
sidebarLayout(
sidebarPanel(
sliderInput("bins",
"Number of bins:",
min = 1,
max = 50,
value = 30)),
mainPanel(plotOutput("distPlot1")))),
tabPanel('my app2',
titlePanel("Old Faithful Geyser Data2"),
sidebarLayout(
sidebarPanel(
sliderInput("bins",
"Number of bins:",
min = 1,
max = 50,
value = 30)),
mainPanel(plotOutput("distPlot2")))),
tabPanel( value= "search_panel",
textInput("search", label=NULL, value="Search"))
)
server <- function(input, output, session) {
observe({
if(!is.null(input$test)){
if(input$test=="search_panel") # Go back to last active panel
updateNavbarPage(session, 'test', selected = selected_panel)
else # Save active panel
selected_panel <<- input$test
}
})
searchtext <- reactive({
if(!is.null(input$search))
if(input$search!="Search")
return(input$search)
return(NULL)
})
output$distPlot1 <- renderPlot({
x <- faithful[, 2]
bins <- seq(min(x), max(x), length.out = input$bins + 1)
hist(x, breaks = bins, col = 'darkgray', border = 'white',
main=ifelse(is.null(searchtext()), "Alt title 1", searchtext()))
})
output$distPlot2 <- renderPlot({
x <- faithful[, 2]
bins <- seq(min(x), max(x), length.out = input$bins + 1)
hist(x, breaks = bins, col = 'darkgray', border = 'white',
main=ifelse(is.null(searchtext()), "Alt title 2", searchtext()))
})
}
shinyApp(ui, server)