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 ;.
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)
In my app, I need to display a single pre-rendered image amongst other UI elements. I'd like the other elements to wrap tightly around the top and bottom of image. The image displayed depends on the state of the app, and the images may be of different sizes.
This question addresses a similar problem, but seems to differ in that many images of different sizes need to be displayed simmultaneously.
Here is a MWE displaying the problem. You can either supply your own images, or download them along with the rest of my RStudio project here.
library(shiny)
library(png)
ui <- fluidPage(
tags$head(tags$link(rel="stylesheet", type="text/css", href="stylesheet.css")),
selectInput("size", label="Size:", choices=c("small", "large")),
imageOutput("image"),
# uiOutput("imageUI"),
textOutput("info")
)
# Define server logic required to draw a histogram
server <- function(input, output) {
imgFileName <- reactive({
paste0("./www/", input$size, ".png")
})
imgFile <- reactive({
readPNG(imgFileName(), info=TRUE)
})
imgSize <- reactive({
info <- unlist(stringr::str_split(attr(imgFile(), "info")$dim, stringr::fixed(" ")))
info <- paste0(info, "px")
names(info) <- c("width", "height")
info <- as.list(info)
info
})
output$info <- renderText({
paste0("Height: ", imgSize()$height, "; Width: ", imgSize()$width)
})
output$image <- renderImage({
list(
src=imgFileName(),
contentType="image/png",
width=imgSize()$width,
height=imgSize()$height,
alt=paste0("A ", input$size, " image"),
class="myImageClass"
)
})
# output$imageUI <- renderUI({
# tagList(plotOutput("image"))
# })
}
shinyApp(ui, server)
If you run the MWE, you'll see that there is a large gap between the image and the text output when the value of the select input is small and the image overlaps the text output when the select input is large.
These screenshots display the desired behaviour.
Examining the underlying HTML (in Firefox, right click anywhere on the image and select "Inspect Element"), the problem appears to be caused by the div that wraps the image:
The img has picked up the image's size correctly, but the surrounding elements are being held in place by the inline height attribute of the surrounding div. To demonstrate that this is the problem, I can disable the offending height attribute in Firefox's inspector:
and this gives me the desired behaviour.
If the problem was caused by one of the CSS classes referenced in the div, I could probably solve the problem by overwriting the class definition in the app's stylesheet. But the offending attribute is inline, so that's not an option.
How can I modify the attributes of the div that wraps the img that displays the image?
You were really close with uiOutput() which is necessary because you want the layout of the UI to change. Whereas what you have uncommented only swaps the images in and out but keeps the UI layout constant.
library(shiny)
library(png)
ui <- fluidPage(
tags$head(tags$link(rel="stylesheet", type="text/css", href="stylesheet.css")),
selectInput("size", label="Size:", choices=c("small", "large")),
# don't use imageOutput() here because the UI will not be able to change
#imageOutput("image"),
# instead use uiOutput() which will allow you to update the UI itself
# that is, you will be able to update the height of the image div reactively
uiOutput("imageUI"),
textOutput("info")
)
server <- function(input, output) {
imgFileName <- reactive({
paste0("./www/", input$size, ".png")
})
imgFile <- reactive({
readPNG(imgFileName(), info=TRUE)
})
imgSize <- reactive({
info <- unlist(stringr::str_split(attr(imgFile(), "info")$dim, stringr::fixed(" ")))
info <- paste0(info, "px")
names(info) <- c("width", "height")
info <- as.list(info)
info
})
output$info <- renderText({
paste0("Height: ", imgSize()$height, "; Width: ", imgSize()$width)
})
output$image <- renderImage({
list(
src=imgFileName(),
contentType="image/png",
width=imgSize()$width,
height=imgSize()$height,
alt=paste0("A ", input$size, " image"),
class="myImageClass"
)
})
# update the UI here by changing the height of the image div
output$imageUI <- renderUI({
imageOutput("image", height = imgSize()$height)
})
}
shinyApp(ui, server)
I have taken a sample code of one of the Shiny Flexdashboard.
In the sample code there is a drop down menu to select one region at a time.
I just want to know is there a way to select all the values in the drop down menu?
Kindly find the code in below link,
beta.rstudioconnect.com/jjallaire/shiny-embedding
for code, click "Source Code" on the top extreme right.
Regards,
Mohan
You can do
library(shiny)
ui = fluidPage(
selectInput("sel", NULL, letters[1:2], multiple = T),
actionButton("but", "all")
)
server <- function(input, output, session) {
observeEvent(input$but, {
updateSelectInput(session, "sel", selected = letters[1:2])
})
}
shinyApp(ui, server)
Use ?updateSelectInput to access the documentation on that function.
I created a table containing some HTML links using Shiny's renderDataTable. The links are not clickable, though, instead they render literally:
https://samizdat.shinyapps.io/zakazky/
Do you have any idea what could be wrong? It worked fine before upgrading Shiny to the version 0.11... Thanks!
I had the same problem. The escape = FALSE option for renderDataTable solved it, as you mentioned in the comments.
Here is complete code for an app with a table that has links.
If you are doing this, you will want each link to be unique based on a value in the table. I move this code into a function so its cleaner.
#app.R#
library(shiny)
createLink <- function(val) {
sprintf('Info',val)
}
ui <- fluidPage(
titlePanel("Table with Links!"),
sidebarLayout(
sidebarPanel(
h4("Click the link in the table to see
a google search for the car.")
),
mainPanel(
dataTableOutput('table1')
)
)
)
server <- function(input, output) {
output$table1 <- renderDataTable({
my_table <- cbind(rownames(mtcars), mtcars)
colnames(my_table)[1] <- 'car'
my_table$link <- createLink(my_table$car)
return(my_table)
}, escape = FALSE)
}
shinyApp(ui, server)
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)