I'm working on a dashboard where sometimes I need to call the input's choice name and other times it's value, but I only know how to get the latter. Is there a way to call the first one?
Here is a minimum reproducible example:
library(shiny)
library(shinydashboard)
ui <- dashboardPage(
header = dashboardHeader(),
sidebar = dashboardSidebar(),
body = dashboardBody(
selectInput(
"input",
h5("The output should give the choice name instead of it's value"),
choices=c(
"Name 1" = 1,
"Name 2" = 2,
"Name 3" = 3
)
),
textOutput("output")
)
)
server <- function(input, output, session) {
output$output <- renderPrint({paste(input$input)})
}
shinyApp(ui = ui, server = server)
I think it is easiest to create a data.frame with the choices and the corresponding names in advance, and use that to look up the name of the selected input. A working example is given below, hope this helps!
library(shiny)
library(shinydashboard)
choices_df = data.frame(
names = c('Name 1', 'Name 2', 'Name 3'),
id = seq(3)
)
ui <- dashboardPage(
header = dashboardHeader(),
sidebar = dashboardSidebar(),
body = dashboardBody(
selectInput(
"input",
h5("The output should give the choice name instead of it's value"),
choices= setNames(choices_df$id,choices_df$names)
),
textOutput("output")
)
)
server <- function(input, output, session) {
output$output <- renderPrint({paste(choices_df$names[choices_df$id==input$input])})
}
shinyApp(ui = ui, server = server)
Related
Does anyone know how to make the title of a tabBox go above the tabs in a shinydashboard app? For example, in the figure below, the title is on the right, but I would like it to go on top of the box.
Code for this tabBox:
library(shiny)
library(shinydashboard)
ui = dashboardPage(dashboardHeader(title = "tabBoxes"), dashboardSidebar(),
dashboardBody(
fluidRow(
tabBox(title = HTML("Hello friend<br>"),
tabPanel("merp", "hi there"),
tabPanel("derp", "hello"),
tabPanel("herp", "howdy")
))
)
)
server = function(input, output) {
# The currently selected tab from the first box
output$tabset1Selected <- renderText({
input$tabset1
})
}
shinyApp(ui = ui, server = server
)
For those who might look for the solution here, a pretty simple fix was to put the tabBox (with no title) inside of a box with a title:
library(shiny)
library(shinydashboard)
ui = dashboardPage(dashboardHeader(title = "tabBoxes"), dashboardSidebar(),
dashboardBody(
fluidRow(box(title = HTML("Hello friend<br>"),
tabBox(
tabPanel("merp", "hi there"),
tabPanel("derp", "hello"),
tabPanel("herp", "howdy"))
))
)
)
server = function(input, output) {
# The currently selected tab from the first box
output$tabset1Selected <- renderText({
input$tabset1
})
}
shinyApp(ui = ui, server = server)
There is the side argument e.g
library(shiny)
library(shinydashboard)
body <- dashboardBody(
fluidRow(
tabBox(
title = "First tabBox",
# The id lets us use input$tabset1 on the server to find the current tab
id = "tabset1", height = "250px",side = 'right',
tabPanel("Tab1", "First tab content"),
tabPanel("Tab2", "Tab content 2")
)
))
shinyApp(
ui = dashboardPage(dashboardHeader(title = "tabBoxes"), dashboardSidebar(), body),
server = function(input, output) {
# The currently selected tab from the first box
output$tabset1Selected <- renderText({
input$tabset1
})
}
)
The given R shiny script has a selectInput and infobox below, I just want to display the selected value in the selectInput within the infobox in the ui. Please help me with a solution and if possible, kindly avoid any scripting in the sever as I have furthur dependency. If this can be done within the UI, would be great, thanks.
## app.R ##
library(shiny)
library(shinydashboard)
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(),
dashboardBody(
box(title = "Data", status = "primary", solidHeader = T, width = 12,
fluidPage(
fluidRow(
column(2,offset = 0, style='padding:1px;',
selectInput("select the
input","select1",unique(iris$Species)))
))),
infoBox("Median Throughput Time", iris$Species)))
server <- function(input, output) { }
shinyApp(ui, server)
Trick is to make sure you know where the value of the selectInput is being assigned, which is selected_data in my example, this can be referenced within the server code by using input$selected_data.
renderUI lets you build a dynamic element which can be rendered with uiOutput and the output id, in this case, info_box
## app.R ##
library(shiny)
library(shinydashboard)
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(),
dashboardBody(
box(title = "Data", status = "primary", solidHeader = T, width = 12,
fluidPage(
fluidRow(
column(2, offset = 0, style = 'padding:1px;',
selectInput(inputId = "selected_data",
label = "Select input",
choices = unique(iris$Species)))
)
)
),
uiOutput("info_box")
)
)
# Define server logic required to draw a histogram
server <- function(input, output) {
output$info_box <- renderUI({
infoBox("Median Throughput Time", input$selected_data)
})
}
# Run the application
shinyApp(ui = ui, server = server)
I need my Shiny module to hide/show a div outside of the namespace. I tried passing the div id to the module server function and using shinyjs to show/hide it but that is not working. I'm not getting an error, it just doesn't show/hide the div.
I know the Shiny module documentation says modules cannot access outputs outside the namespace. The docs do, though, give a way for the module to access inputs outside the namespace using reactives.
Does anyone know if there is a way for a Shiny module to access an output outside the namespace?
Here is what I'm trying to do:
### ui.R ###
header <- dashboardHeader(
title = a(href = 'http://google.com')
)
dashboardPage(
skin = 'black',
header,
dashboardSidebar(
sidebarMenu( id='tabs',
menuItem('Edit Existing Client', tabName = 'client-info')
)),
dashboardBody(
useShinyjs(),
fluidRow(
tabItems(
tabItem(tabName = "client-info",
div(selectClientModuleUI("clientinfons")),
div(id='editclientinfo', uiOutput('editclientstuff'))
)
)
)
)
)
### server.R ###
shinyServer(function(session,input, output) {
output$editclientstuff <- renderUI({
div(
fluidRow(
column(6,
textInput('editname', "Display name", value ='Testing name')
),
column(6,
numericInput('editastart','Start', value ='3')
)
)
)
})
callModule(selectClientModule, 'clientinfons', 'editclientinfo')
shinyjs::hide(id='editclientstuff')
})
### in global.R ###
selectClientModuleUI <- function(id){
ns <- NS(id)
clientlist = c(0, 1, 2)
names(clientlist) = c('Choose client', 'Fred', 'Kim')
div(
selectInput(ns('selectclient'), 'Select client to edit', choices = clientlist, selected = NULL, multiple = FALSE)
)
}
selectClientModule <- function(input, output, session, divtoshow = ''){
observeEvent(input$selectclient, {
if (!is.null(input$selectclient) && input$selectclient > 0){
print(paste0("showing ", divtoshow))
shinyjs::show(divtoshow)
}
})
}
That is possible by giving the value as a reactive (not as the value of the reactive) to the module. You can change the reactive Value in the module and return the reactive from the Module to the app (note, return the reactive itself, not its value). The following app switches the 'divtoshow' in the main app from inside the module. If nothing is selected, it's hidden, otherwise it's shown (note, I adjusted you code a little so it's working as a stand-alone app):
library(shinydashboard)
library(shinyjs)
# Module
selectClientModuleUI <- function(id){
ns <- NS(id)
clientlist = c(0, 1, 2)
names(clientlist) = c('Choose client', 'Fred', 'Kim')
div(
selectInput(ns('selectclient'), 'Select client to edit', choices = clientlist, selected = NULL, multiple = FALSE)
)
}
selectClientModule <- function(input, output, session, divtoshow){
observeEvent(input$selectclient, {
if (input$selectclient > 0){
print(paste0("showing editclientinfo"))
divtoshow("editclientinfo") # set the div to show to "editclientinfo", this will be visible outside the module
}else{
divtoshow("") # set the div to show to "", if nothing was chosen
}
})
# return the div to show as reactive to the main app
return(divtoshow)
}
# Main App
ui <- shinyUI(
dashboardPage(
skin = 'black',
dashboardHeader(
title = a(href = 'http://google.com')
),
dashboardSidebar(
sidebarMenu( id='tabs',
menuItem('Edit Existing Client', tabName = 'client-info')
)),
dashboardBody(
useShinyjs(),
fluidRow(
tabItems(
tabItem(tabName = "client-info",
div(selectClientModuleUI("clientinfons")),
div(id='editclientinfo', uiOutput('editclientstuff'))
)
)
)
)
))
server <- shinyServer(function(session,input, output) {
output$editclientstuff <- renderUI({
div(
fluidRow(
column(6,
textInput('editname', "Display name", value ='Testing name')
),
column(6,
numericInput('editastart','Start', value ='3')
)
)
)
})
# store the div to show in a reactive
divtoshow <- reactiveVal('')
# divtoshow can be changed in side this module, so it's a return value
divtoshow <- callModule(selectClientModule, 'clientinfons', divtoshow)
# observe the value of divtoshow and toggle the corresponding div
observeEvent(divtoshow(), {
if(divtoshow() == "editclientinfo"){
shinyjs::show("editclientinfo")
}else{
shinyjs::hide("editclientinfo")
}
})
})
shinyApp(ui, server)
I have a shiny application where I want to build a conditional query system on a data frame.
First, I want to have a selectInput showing all available tables. After the user has chosen a table, I want another box to appear where he can select the column name he wants to filter for. This is what I have until now:
ui.r:
library(shiny)
library(shinydashboard)
source("global_variables.r")
ui=dashboardPage(
dashboardHeader(title="Test"),
dashboardSidebar(
sidebarMenu(
menuItem("Conditionals",tabName = "conditionals")
)
),
dashboardBody(
tabItems(
tabItem(tabName="conditionals",
fluidRow(
box(
title = "Conditionals",
width = 4,
selectInput("Con_tableName",choices=c("NONE",tableNames),label = "Table Name"),
tags$div(id = 'placeholder')
)
)
)
)
)
)
server.r:
library(shiny)
source("global_variables.r", local = FALSE)
Table1=data.frame();
shinyServer(
function(input, output,session) {
observe({
reactive(
if(input$Con_tableName!="NONE"){
insertUI( selector="#placeholder",
ui={
selectInput("Con_colName",choices=c("NONE",colnames(dynGet(input$Con_tableName))),label = "Column Name")
}
)
}
)
})
}
)
global_variables.r:
tableNames=c("Table1","Table2","Table3")
The problem is, that if I choose a value in the selectInput, observe doesnt get fired.
EDIT:
According to BigDataScientists comment,changed insertUI to renderUI. Updated files:
ui.r:
library(shiny)
library(shinydashboard)
source("global_variables.r")
ui=dashboardPage(
dashboardHeader(title="Test"),
dashboardSidebar(
sidebarMenu(
menuItem("Conditionals",tabName = "conditionals")
)
),
dashboardBody(
tabItems(
tabItem(tabName="conditionals",
fluidRow(
box(
title = "Conditionals",
width = 4,
selectInput("Con_tableName",choices=c("NONE",tableNames),label = "Table Name"),
uiOutput("conditionalUI")
)
)
)
)
)
)
server.r:
library(shiny)
source("global_variables.r", local = FALSE)
Table1=data.frame();
shinyServer(
function(input, output,session) {
observeEvent(input$Con_tableName,{
reactive(
if(input$Con_tableName!="NONE"){
output$conditionalUI=renderUI({
selectInput("Con_colName",choices=c("NONE",colnames(input$Con_tableName)),label = "Column Name")
})
}
)
})
}
)
You can use conditionalPanel(). Below there is a small example which might work in your case.
library(shiny)
shinyApp(
ui <- fluidPage(
mainPanel(
selectInput("input1", "Select something", choices = c('','1','2','3')),
conditionalPanel("input.input1!=''",
selectInput('input2', "Select something else", choices = c('4','5')))
)
),
server <- function(input, output){}
)
I'm trying to generate multiple menuItems dynamically, may be simple, but I'm not getting the right idea.
library(shiny)
library(shinydashboard)
port_tables<-c("tab1","tab2","tab3","tab4") # These are from a DB connection in the original code
function(input, output) {
output$smenu1 <- renderMenu({
sidebarMenu( id = "tabs",
h4("Tables",style="color:yellow;margin-left:20px;"),
paste("menuItem(\"",port_tables,"\",tabName=\"",port_tables,"\",icon=icon('th'))",collapse=",")
)
})
)
The menuItems from the paste function doesn't resolve( I get the result of paste function on the sidebar). I tried eval, eval(parse(paste(...))), both didn't work - what am I missing?
I couldn't quite make out what you're asking for, but here's an example of something with a dynamic menu.
library(shiny)
library(shinydashboard)
ui <- dashboardPage(
dashboardHeader(title = "Dynamic Menu"),
dashboardSidebar(
sidebarMenuOutput(outputId = "dy_menu")
),
dashboardBody(
tabItems(
tabItem(tabName = "main",
textInput(inputId = "new_menu_name",
label = "New Menu Name"),
actionButton(inputId = "add",
label = "Add Menu")
)
)
)
)
server <- function(input, output, session){
output$dy_menu <- renderMenu({
menu_list <- list(
menuItem("Add Menu Items", tabName = "main", selected = TRUE),
menu_vals$menu_list)
sidebarMenu(.list = menu_list)
})
menu_vals = reactiveValues(menu_list = NULL)
observeEvent(eventExpr = input$add,
handlerExpr = {
menu_vals$menu_list[[length(menu_vals$menu_list) + 1]] <- menuItem(input$new_menu_name,
tabName = input$new_menu_name)
})
}
shinyApp(ui, server)
I changed the code as follows and it worked :
library(shiny)
library(shinydashboard)
port_tables<-c("tab1","tab2","tab3","tab4") # These are from a DB connection in the original code
text1<-paste("menuItem(\"",port_tables,"\",tabName=\"",port_tables,"\",icon=icon('th'))")
text2<-paste("sidebarMenu(id = 'tabs',textInput('port', 'Enter port:'),h4('Tables',style='color:yellow;margin-left:20px;'),",paste(text1,collapse=","),paste(")"))
function(input, output) {
output$smenu1 <- renderMenu({
eval(parse(text=text2))
})
)
So, the key is put the whole content of sidebarMenu in a text field and evaluate it