Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Place button next to selectInput

Goal

I want to place a selectInput and an actionButton side by side in the footer of my shinydashboard::box. The button should be "relatively close" to the selectInput irrespective of the width of the box.

What I have tried so far

So far I tried column, splitLayout or styling via display: inline-block, but I am not happy with either of the solutions:

  • column: depending on the width of the box, the gap between selectInput and actionButton is too big (I could partially solve that by extending the selectInput width to 100%, but then the width is too large)
  • splitDesign: best option so far, but cellWidths needs adaptation based on box width and works also only with 100% selectInput width and for big boxes, the width of the second split seems to be too big
  • inline-block: does not play well with the general CSS

Example

library(shiny)
library(purrr)
library(shinydashboard)

widths <- c(1, 2,3, 4, 6, 12)

makeBoxes <- function(width, method = c("split", "col", "css")) {
   method <- match.arg(method)
   split <- function(width, count) {
      splitLayout(selectInput(paste("sel", width, count, sep = "_"), NULL, LETTERS,
                              width = "100%"),
                  actionButton(paste("ab", width, count, sep = "_"), icon("trash")),
                  cellWidths = c("87.5%", "12.5%"),
                  cellArgs = list(style = "vertical-align: top"))
   }
   col <- function(width, count) {
      fluidRow(column(width = 11,
                      selectInput(paste("sel", width, count, sep = "_"), NULL, LETTERS,
                                  width = "100%")),
               column(width = 1,
                      actionButton(paste("ab", width, count, sep = "_"), icon("trash"))))
   }

   css <- function(width, count) {
      fluidRow(div(selectInput(paste("sel", width, count, sep = "_"), NULL, LETTERS),
                   style = "display: inline-block; vertical-align: top"),
               actionButton(paste("ab", width, count, sep = "_"), icon("trash")))
   }

   wrap <- function(method, ...)
      switch(method, split = split(...), col = col(...), css = css(...))

   map(seq(1, 12 / width, 1), function(count)
      box(solidHeader = TRUE, title = "Box", status = "info", width = width,
          footer = wrap(method, width, count)))
}

server <- function(input, output) {
}

ui1 <- dashboardPage(dashboardHeader(), dashboardSidebar(),
                     dashboardBody(map(widths, ~ fluidRow(makeBoxes(.x, "split")))))
ui2 <- dashboardPage(dashboardHeader(), dashboardSidebar(),
                     dashboardBody(map(widths, ~ fluidRow(makeBoxes(.x, "col")))))
ui3 <- dashboardPage(dashboardHeader(), dashboardSidebar(),
                     dashboardBody(map(widths, ~ fluidRow(makeBoxes(.x, "css")))))

shinyApp(ui1, server)
shinyApp(ui2, server)
shinyApp(ui3, server)
like image 915
thothal Avatar asked Jul 25 '18 15:07

thothal


1 Answers

I hope this could can be useful. I change width = 11 to 12 and it seems good to me.

Is that what you want ?

library(shiny)
library(purrr)
library(shinydashboard)

widths <- c(1, 2,3, 4, 6, 12)

makeBoxes <- function(width, method = c("split", "col", "css")) {
method <- match.arg(method)
split <- function(width, count) {
  splitLayout(selectInput(paste("sel", width, count, sep = "_"), NULL, LETTERS,
                          width = "100%"),
              actionButton(paste("ab", width, count, sep = "_"), icon("trash")),
              cellWidths = c("87.5%", "12.5%"),
              cellArgs = list(style = "vertical-align: top"))
}
col <- function(width, count) {
  fluidRow(column(width = 12,  # width = 11 -> 12
                  selectInput(paste("sel", width, count, sep = "_"), NULL, LETTERS,
                              width = "100%")),
           column(width = 1,
                  actionButton(paste("ab", width, count, sep = "_"), icon("trash"))))
}

 css <- function(width, count) {
  fluidRow(div(selectInput(paste("sel", width, count, sep = "_"), NULL, LETTERS),
               style = "display: inline-block; vertical-align: top"),
           actionButton(paste("ab", width, count, sep = "_"), icon("trash")))
}

 wrap <- function(method, ...)
  switch(method, split = split(...), col = col(...), css = css(...))

map(seq(1, 12 / width, 1), function(count)
  box(solidHeader = TRUE, title = "Box", status = "info", width = width,
      footer = wrap(method, width, count)))
}

server <- function(input, output) {
}

ui2 <- dashboardPage(dashboardHeader(), dashboardSidebar(),
                 dashboardBody(map(widths, ~ fluidRow(makeBoxes(.x, "col")))))

shinyApp(ui2, server)
like image 133
Alex Yahiaoui Martinez Avatar answered Nov 01 '22 18:11

Alex Yahiaoui Martinez