I have a pair of DT datatables in my shiny app. I would like to control the width of one of these tables (via fixed-width) while leaving the width of the other table dynamic.
After trialing a number of approaches for fixing columns widths, the one that seems best for my application is to use the styling table.dataTable {table-layout: fixed;}. However, this effects both tables.
How can I limit the effect of this style to just the second table?
data(starwars)
starwars = starwars[1:5,1:4]
ui = fluidPage(
DT::dataTableOutput("variable_width"),
tags$style(HTML("table.dataTable {table-layout: fixed;}")),
DT::dataTableOutput("fixed_width")
)
server = function(input, output, session){
output$variable_width = DT::renderDataTable({ starwars }, options = list(dom = "t"))
output$fixed_width = DT::renderDataTable({ starwars }, options = list(dom = "t"))
}
shinyApp(ui, server)
From searching, it looks like this should be possible via div: That you can limit styling to only the current div. However, I am unable to get this working.
You need to add what are the parents div in you CSS, like this :
tags$style(HTML("#fixed_width > .dataTables_wrapper > table.dataTable {table-layout: fixed;}")),
With #fixed_width being the outputId (which is also a div id) of you second table.
Related
I'm trying to adjust the positioning of conditionally-rendered objects in R shiny. When running the below skeleton code and clicking the "Delete" action button, I'd like to nudge the conditionally-rendered text ("Select series to delete >>") a bit to the right, and move the little selectInput() box that also conditionally appears on the far right a bit to the left, closer to "Select series to delete >>". I've fiddled with column widths, etc., and I've exhausted all the formatting options which I know of which are limited. Any suggestions for fine-tuning the positioning of these items? My guess is this would entail some CSS which I know almost nothing about.
Skeleton code:
library(dplyr)
library(shiny)
library(shinyjs)
toggleView <- function(input, output_name){
observeEvent(input$delSeries, {show(output_name)})
observeEvent(input$addSeries, {hide(output_name)})
}
ui <- fluidPage(br(),
useShinyjs(),
fluidRow(
column(1,actionButton("addSeries", "Add",width = '70px')),
column(1,actionButton("delSeries","Delete",width = '70px')),
column(3,h5((hidden((textOutput("delFlag")))))),
column(3,hidden(uiOutput("delSeries2")))
)
)
server <- function(input, output, session) {
output$delFlag <- renderText("Select series to delete >>")
output$delSeries2 <-
renderUI(
selectInput("delSeries3",
label = NULL,
choices = c(""),
selected = "",
width = '110px')
)
toggleView(input,"delSeries2")
toggleView(input,"delFlag")
}
shinyApp(ui,server)
You can add some styles to the 2 columns like so:
library(dplyr)
library(shiny)
library(shinyjs)
toggleView <- function(input, output_name){
observeEvent(input$delSeries, {hide(output_name)})
observeEvent(input$addSeries, {show(output_name)})
}
# (0)
css <- HTML("
.row .nudge-right {
padding-right:0;
}
.row .nudge-left {
padding-left:0;
}
")
ui <- fluidPage(
tags$head(tags$style(css)), # (1)
br(),
useShinyjs(),
fluidRow(
column(1,actionButton("addSeries", "Add",width = '70px')),
column(1,actionButton("delSeries","Delete",width = '70px')),
column(3,h5(hidden(textOutput("delFlag"))),
class = c("nudge-right", "text-right")), # (2)
column(3,hidden(uiOutput("delSeries2")), class = "nudge-left") # (2)
)
)
Explanation
The white space you see is partly due to the width of the column and partly due to the so called padding (an additional white space around the element). To bridge this gap you can:
Right align the text. Here you can rely on the already pre-defined (by the underlying bootstrap framework) class text-right.
Further decrease the gap by removing the right padding from the text column and the left padding from the input column. In order to so, you define new classes (I called them .nudge-right and .nudge-left respectively) where you deliberately set the padding to your liking (here I removed it completely, you may want to provide a small offset though - e.g. 5px).
Then all which is left is to
Create some css with the class definitions (#0)
Load the css (#1)
Assign the classes to the columns (#2)
I am attempting to arrange the following outputs so that each number pair is aligned perfectly.
Is there a way to change the spacing of a table beyond the options avaible e.g 'l'?
Following this, how could I vertically align the table with the bucketlist?
library(shiny)
library(sortable)
ui <- fluidPage(column(width =1,tableOutput("table")), column(width =1,
uiOutput("numbers"))
)
server <- function(input, output, session) {
output$table = renderTable( spacing = 'l',as.matrix(c(1:30)))
output$numbers <- renderUI({
bucket_list(
header = h4("Numbers", align = "center"),
group_name = "rank_Bedspace_Acuity",
orientation = "horizontal",
add_rank_list(
text = h5("Numbers", align = "center",style="color: #fff; background-color: #4080C9"),
input_id = "numbers",
labels = c(1:30)
))
})
}
shinyApp(ui, server)
Help appreciated.
Spacing of table - You will have to tweak the .css on your own.
I took your code and made the following updates to .css
Set table
width: auto; - Deleted this
padding-top: 15px; - Added this
.tr { padding-bottom: 1px }
(this is to match with the sortable height of 42px. Alternatively, you could also update the row height directly.
I assume by vertical alignment, you want the table to appear right next to the sortable widget so that you get a reference between old table vs the updated one. Applying the above .css tweaks, I get the following
Is this what you were looking for?
I am building a table using the DT package in a Shiny Dashboard. The table has several columns and I used DT's ColVis functionality to allow users to hide/show only the columns they're interested in.
My question is - is it possible to change the color of those buttons once the Column visibility button is clicked on? As of right now, the colors aren't different enough and its hard to tell which columns are visible and which ones aren't without navigating to the table. I've included a screenshot that shows what I mean. The Site_ID column is not visible in the table, while the Participant_ID column is.
I used inspect element in google chrome to find out the objects name and it looked to be: a.dt-buttons.buttons-columnVisibility, and was under body.skin-blue, div.dt-button-collection.
Using this info I added the following line to my ui.R code:
tags$head(tags$style(HTML(".skin-blue .dt-button-collection .buttons-columnVisibility .active a{background-color: #4d4d4d}")))
But this didn't appear to do anything. Any help on implementing this custom CSS/HTML into my dashboard would be appreciated.
Based on this answer, it looks like the button color needs to be set with background. I also used !important to override the DT button style, although this may not be the best practice.
Here's a small working example:
library(DT)
library(shiny)
ui <- basicPage(
tags$head(
tags$style(
HTML(
".dt-button.buttons-columnVisibility {
background: #FF0000 !important;
color: white !important;
opacity: 0.5;
}
.dt-button.buttons-columnVisibility.active {
background: black !important;
color: white !important;
opacity: 1;
}"
)
)
),
h2("The iris data"),
DT::dataTableOutput("mytable")
)
server <- function(input, output) {
output$mytable = DT::renderDataTable({
datatable(
iris, rownames = FALSE,
extensions = 'Buttons',
options = list(dom = 'Bfrtip', buttons = I('colvis'))
)
})
}
shinyApp(ui, server)
Is there a way to hide column names of a formattable? I thought about
changing an attribute in the formattable options. Didn't find something about it in the documentation or SO.
changing the font color to white for the header. I guess this may be an easy task for a CSS expert. I couldn't find the right sources to do it as a layman.
Maybe there is another option that I didn't think of? Thanks for your help in advance.
Example code below. The right table's header should be hidden.
library(shiny)
library(formattable)
df <- data.frame(A = LETTERS[1:10], B = 1:10)
server <- function(input, output) {
output$table1 <- renderFormattable({
formattable(df)
})
output$table2 <- renderFormattable({
formattable(df)
})
}
ui <- fluidPage(
fluidRow(
column(6,
h6("Table with header"),
formattableOutput("table1")
),
column(6,
h6("Table without header"),
formattableOutput("table2")
)
)
)
shinyApp(ui = ui, server = server)
Additional: If there is a way to set cell borders like in Excel for the
right table, solutions to this problem would also be appreciated.
Not exactly hiding, but here is my simple suggestion:
output$table2 <- renderFormattable({
names(df) <- c("_", ".")
formattable(df)
})
Any help to your problem?
Add this to your code:
tags$head(tags$style(type = "text/css", "#table2 th {display:none;}"))
Note that you will need to manually set the widths of your columns as they will collapse to the smallest width without text overflowing to a new line.
What I've done here is used some CSS to tap into table2's properties. I access the header properties by declaring th after stating the table's ID. Any additional css for the header can go after the ;.
I would like to get a DataTable (with all its ranking, search and page features) that does not stretch fully across the page, and results in large amounts of white space in each column...
... ideally with column widths similar to the "wrap" style from renderTable...
I know I can fix relative column widths, however, my table will dynamically update with different numbers of columns dependent of inputs selected. I would prefer additional columns to expand into the empty space on the right hand side and then trigger a horizontal scrollbar if it becomes wider than the browser window width.
Reproducible example of the tables in the images above...
library(shiny)
runApp(list(
ui = navbarPage(
title = 'Tables',
tabPanel('dataTableOutput', dataTableOutput('ex1')),
tabPanel('tableOutput', tableOutput('ex2'))
),
server = function(input, output) {
output$ex1 <- renderDataTable(iris)
output$ex2 <- renderTable(iris)
}
))
I think that you should use drawCallback in dataTables. Here I just changed your example a little to fix width of dataTable to 600px. you can play with possible java script function in callback function to do almost anything.
library(shiny)
runApp(list(
ui = navbarPage(
title = 'Tables',
tabPanel('dataTableOutput', dataTableOutput('ex1')),
tabPanel('tableOutput', tableOutput('ex2'))
),
server = function(input, output) {
output$ex1 <- renderDataTable( iris,
option = list( drawCallback = I("function( settings ) {document.getElementById('ex1').style.width = '600px';}")) )
output$ex2 <- renderTable(iris)
}
))
Assuming your data.frame is df, then put this code at the beginning of the reactive/renderTable block at the server side. It will wrap the column names to desirable length and therefore reducing the size of the table. You can always change the width to equal the desired width.
library(stringr)
colnames(df) = str_wrap(colnames(df),width = 10)