Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to overcome width parameter in shinyDashboard valueBox being ignored when wrapped in renderUI and htmlOutput

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.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

enter image description here

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

>Solution :

Change htmlOutput to valueBoxOutput:

  output$stats <- renderUI({
    vboxes <- lapply(1:nstats, function(i) {
      outputId <- paste0("valuebox_", i)
      valueBoxOutput(outputId)
    })
    tagList(vboxes)
  })

enter image description here

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.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading