djc55
djc55

Reputation: 555

Dynamically changing sidebar width based on an input

Is there anyway to dynamically change the sidebar width based on an input value? In the example below, I would like the width of the sidebar to be based on the sidebarWidth input:

library(shiny)
library(shinydashboard)

ui <- dashboardPage(
  dashboardHeader(),
  dashboardSidebar(width = 230),
  dashboardBody(
    numericInput("sidebarWith", "Select Sidebar Width", min = 300, max = 500, value = 230)
  )
)

server <- function(input, output) { }

shinyApp(ui, server)

Upvotes: 1

Views: 567

Answers (2)

lz100
lz100

Reputation: 7330

Let's try this fast, responsive, no server code version, pure Javascript.

library(shiny)
library(shinydashboard)

ui <- dashboardPage(
    dashboardHeader(),
    dashboardSidebar(width = 230),
    dashboardBody(
        numericInput("sidebarWith", "Select Sidebar Width", min = 230, max = 500, value = 230),
        tags$script(HTML(
        '
        $(function(){
            var mainContent = $(".wrapper > .content-wrapper");
            var curWidth = 230;
            $("#sidebarWith").on("change", function() {
                if(parseFloat($(this).val()) < 230 || parseFloat($(this).val()) > 500) {return false}
                curWidth = $(this).val();
                mainContent.css("margin-left", `${curWidth}px`);
                $(".main-header .navbar").css("margin-left", `${curWidth}px`);
                $(".main-header .logo").css("width", `${curWidth}px`);
            });
            $(".sidebar-toggle").on("click", function() {
                if(!$("body").hasClass("sidebar-collapse")) {
                    mainContent.css("margin-left", `0px`);
                    $(".main-header .navbar").css("margin-left", `0px`);
                    $(".main-header .logo").css("width", `0px`);
                } else {
                    mainContent.css("margin-left", `${curWidth}px`);
                    $(".main-header .navbar").css("margin-left", `${curWidth}px`);
                    $(".main-header .logo").css("width", `${curWidth}px`);
                }
            })
        });
        '
        ))
    )
)

server <- function(input, output) { }

shinyApp(ui, server)
  1. No server code is needed. Apply the UI, server separation design: If we can solve the problem by only using the UI, do it in UI. UI only solutions generally have better performance and speed than UI-server communication.
  2. I noticed there is a button on the top to collapse the sidebar, so I made changes accordingly. When you click it, it will collapse and resume to the right width you set in the numeric input.
  3. Original header left is not collapsed when you click the collapse button, and its width is not changed. I made it align with the width of the sidebar and made it collapse as well when you click the button.

enter image description here

Upvotes: 3

Ben
Ben

Reputation: 30474

I think you could try the following. Use uiOutput in your ui to dynamically change in the server with renderUI. Note that I corrected the spelling of sidebarWidth in the example.

library(shiny)
library(shinydashboard)

ui <- dashboardPage(
  header = dashboardHeader(),
  sidebar = uiOutput("sidebar"),
  body = dashboardBody(
    numericInput("sidebarWidth", "Select Sidebar Width", min = 300, max = 500, value = 230)
  )
)

server <- function(input, output) {
  output$sidebar <- renderUI({
    dashboardSidebar(width = input$sidebarWidth)
  })
}

shinyApp(ui, server)

Upvotes: 1

Related Questions