I am wanting to create shinyDashboard valueBoxes. The number of these is variable depending on select inputs, so I have followed this example to render n valueBoxes using renderUI, htmlOutput and tagList. However when I do this the width parameter in valueBox seems to be ignored and the valueBoxes take up the remaining width of the page and are stacked vertically. If rendered manually within the UI they are the correct width and sit on a single fluid row.
Here is an example. Here the number of valueBoxes is hard coded as 3 but in reality this would be determined by dyanmic data:
library(shiny)
library(shinyWidgets)
library(shinydashboard)
# Define UI for application that draws a histogram
ui <- fluidPage(
useShinydashboard(),
# Application title
titlePanel(title = 'Title'),
sidebarLayout(
sidebarPanel(width = "3",
selectInput(inputId = 'pick', 'Pick a letter',
choices = c('A','B','C'))
),
mainPanel(
uiOutput("stats")
)
)
)
server <- function(input, output, session) {
#how many statistics to show - in reality this will be dynamic
nstats <- 3
stats <- c(-10,0,10)
#dynamically create the right number of htmlOutputs
#https://stackoverflow.com/questions/31686773/shiny-dynamic-number-of-output-elements-plots
output$stats <- renderUI({
vboxes <- lapply(1:nstats, function(i) {
outputId <- paste0("valuebox_", i)
htmlOutput(outputId)
})
tagList(vboxes)
})
#now populate these with valueboxes containing the ith statistic
for(i in 1:nstats){
local({
#my_i <- i
outputId <- paste0("valuebox_", i)
temp <- stats[i]
output[[outputId]] <- renderValueBox({
valueBox(
subtitle = 'Change measure',
width = 2,
value = paste0(temp,"%"),
icon = icon('chart-line')
)
})
})
}
}
# Run the application
shinyApp(ui = ui, server = server)
This generates the following, with the valueBoxes taking up all 9 columns, rather than 2 each.
I have tried inline=TRUE in htmlOutput but this makes no difference. How can I make the width=2 be respected or where do I need to move this to? Thanks
Change htmlOutput
to valueBoxOutput
:
output$stats <- renderUI({
vboxes <- lapply(1:nstats, function(i) {
outputId <- paste0("valuebox_", i)
valueBoxOutput(outputId)
})
tagList(vboxes)
})
As an aside, I think this is a classic example of where using modules would be beneficial. It would mean you wouldn't need to track the valueBox IDs in the server or UI, and could delegate all the manipulation of the data in the value box to the module. This will make your main ui and server functions shorter and cleaner.