I have the following Shiny Application:
library(shiny)
list1 <- c(0.2,0.8,0.5)
list2 <- c("element1", "element2", "element3")
df <- data.frame(list1, list2)
UI <- fluidPage(
formattableOutput("table1")
)
Server <- function(input, output) {
output$table1 <- renderFormattable({
formattable(df, list(
list1 = color_tile("green", "red")
))
})
}
shinyApp(ui = UI, server = Server)
This works fine. However, I am looking for a way to set the column widths. I might be overlooking it in the documentation but I cant find a way to adjust the widths.
Any feedback on how I should change it?
Shiny renders it's code into HTML, so you can actually use CSS to adjust any aesthetic you'd like to change post render. Here's an easy fix using CSS.
First create a directory, www in the app directory, and create a file called styles.css which will serve as your CSS file. Add the following lines to styles.css:
table {
width: 400px !important;
}
This adjusts the width of all tables displayed in your app to be 400px, you can change this value as needed. Next, add includeCSS("www/styles.css") to the UI portion of your app like so:
library(shiny)
list1 <- c(0.2,0.8,0.5)
list2 <- c("element1", "element2", "element3")
df <- data.frame(list1, list2)
UI <- fluidPage(
includeCSS("www/styles.css"),
formattableOutput("table1")
)
Server <- function(input, output) {
output$table1 <- renderFormattable({
formattable(df, list(
list1 = color_tile("green", "red")
))
})
}
shinyApp(ui = UI, server = Server)
This will let Shiny know to use the CSS in the file we just created when rendering the page.
Related
I would like to run a function that has a shiny app inside, but I can't.
Running this example separately, I first remove column one from my input data frame; then I run shiny to change whatever is necessary in the data frame and, when I close the window, a new object is saved with the changes; and finally I create a new column in the data frame.
This is an example script, but I would like that, when executing the function, the shiny window opens and some things are changed in the data frame for the user interactively. Could someone help?
library(shiny)
library(rhandsontable)
my_function <- function(x){
select <- x[,-1]
ui <- fluidPage(
fluidRow(
column(
width = 12,
rHandsontableOutput("myTable")
)))
server <- function(input, output, session) {
# dummy dataframe
df = select
# convert it to a "rhansontable" object
output$myTable <- renderRHandsontable({rhandsontable(df)
})
observeEvent(input$myTable, {
test_df = hot_to_r(input$myTable)
assign('my_data_frame',test_df,envir=.GlobalEnv)
# browser() # uncomment for debugging
})
}
shinyApp(ui, server)
my_data_frame2 <- my_data_frame %>%
mutate(new_column_test = "hello")
return(my_data_frame2)
}
my_function(mtcars)
Hi you almost made it you don't want to return anything but add the data simply using assign
library(shiny)
library(rhandsontable)
myapp_function <- function(data) {
ui <- basicPage(
actionButton("quit", label = "Close"),
actionButton("create", label = "Create copy"),
textInput("name","Set dataframe name", value = "my_data_frame"),
rHandsontableOutput("myTable")
)
server <- function(input, output, session) {
output$myTable <- renderRHandsontable({
rhandsontable(data)
})
observeEvent(input$create, {
assign( input$name, hot_to_r(input$myTable), envir=.GlobalEnv)
})
observeEvent(input$quit,{
stopApp()
})
}
## launch app
shinyApp(ui, server,options=c(shiny.launch.browser = .rs.invokeShinyPaneViewer))
}
## test
myapp_function(iris)
myapp_function(mtcars)
myapp_function(PlantGrowth)
I would suggest to create the ui and server outside of the myapp_function - otherwise it will become a very large function...also creating a function inside another function is not the best practise.
When a DT datatable initilaly renders in a shiny app it appears to grow from the top and push all other elements down the page. Is there a way to render the datatable more smoothly so that other elements are not pushed out of the way like this?
You can see in the example code the h1 renders first at the top of the screen and is then pushed down when the datatable renders. I have tried creating a div with minimum height for the table but it didn't work.
library(shiny)
library(DT)
ui <- fluidPage(
DT::dataTableOutput('table'),
h1('placeholder text'))
server <- function(input, output, session) {
my_data <-
data.frame(
a = rnorm(5000),
b = rnorm(5000),
c = rnorm(5000),
d = rnorm(5000)
)
output$table <- DT::renderDataTable({
datatable(my_data, options = list(pageLength = 25))
})
}
shinyApp(ui, server)
There is some nice functionality in the DT package to reload data smoothly when the data changes after the initial render (using replaceData()). However, I cannot seem to render the data smoothly initially.
So, you can define a height in pixels, but that may not match the pageLength argument you made on the server. I think if you want to control the height in the rendering of the page, the best way to do that is to define height in pixels, not page length. This way the height gets enforced when the page is being loaded AND when the table gets rendered:
library(shiny)
library(DT)
ui <- fluidPage(
DT::dataTableOutput('table', height = "500px"),
h1('placeholder text'))
server <- function(input, output, session) {
my_data <-
data.frame(
a = rnorm(5000),
b = rnorm(5000),
c = rnorm(5000),
d = rnorm(5000)
)
output$table <- DT::renderDataTable({
datatable(my_data)
})
}
shinyApp(ui, server)
I'm trying to take my Shiny apps and break them into smaller files to make collaborating via git with coworkers much easier. This question helped me figure out how to source() in files to my server.r by using source(...,local=T). Now I'm trying to do the same thing with my UI layer.
Consider this toy Shiny app:
library(shiny)
ui <- bootstrapPage(
plotOutput("test"),
numericInput("n","Number of points",value=100,min=1)
)
server <- function(input, output, session) {
output$test = renderPlot({
x = rnorm(input$n)
y = rnorm(input$n)
plot(y~x)
})
}
shinyApp(ui, server)
This app does what you would expect, one overly-wide graph of 100 random data points. Now, what if I want to move just the plotOutput to a separate file (the real use case is in moving whole tabs of UI to separate files). I make a new file called tmp.R and it has:
column(12,plotOutput("test"),numericInput("n","Number of points",value=100,min=1))
The reason for wrapping it in the column statement is because the comma's can't just be hanging out. Now I update my UI to:
library(shiny)
ui <- bootstrapPage(
source("tmp.R",local=T)
)
server <- function(input, output, session) {
output$test = renderPlot({
x = rnorm(input$n)
y = rnorm(input$n)
plot(y~x)
})
}
shinyApp(ui, server)
Now, the word "TRUE" is just hanging out at the bottom of the page.
How do I eliminate this word from showing up? Why is it there?
Try source("tmp.R",local = TRUE)$value maybe
I would like to incorporate a custom font in my Rshiny App. I have a hunch the code would go in tags$style, but haven't the actual code to include this.
Example code:
ui <- fluidPage(
tags$style( ),
column(12,
dataTableOutput("testtab")
) # close column
) #close fluidpage
server <- function(input, output, session) {
output$testtab <-
DT::renderDataTable({
tab <- data.frame(a = 1:10, b = 11:20, c = 21:30)
dat.tab <- datatable(tab) %>% formatPercentage('a', 0) %>%
formatCurrency(1:ncol(tab), '$')
return(dat.tab)
}) # close renderDataTable
} # close server
shinyApp(ui=ui, server=server)
For example's sake, let's say I want to use any custom font out there on the web.
This should help.
First you need to download the font from http://www.fontspace.com/gunarta/surabanglus and install it by clicking on the file with the ttf extension and clicking install. Here I have added tags to control the default body font, and tags that use the "id tag" to control the fonts in specific controls and the background colors.
There are other ways to do this using seperate CSS files, etc. But this is quick and easy and not too dirty.
library(shiny)
library(dplyr)
library(DT)
ui <- fluidPage(
tags$style(HTML('body {font-family:"Times New Roman",Georgia,Serif; background-color:orange}')),
tags$style(HTML('#testtab {font-family:"surabanglus",Georgia,Serif; background-color:lightblue}')),
tags$style(HTML('#hello2 {font-family:"Courier",Georgia,Serif; background-color:pink}')),
column(12,
dataTableOutput("testtab"),
actionButton("hello1","Hello There (uses font inherited from body)"),
actionButton("hello2","Hello There again (uses Courier)")
) # close column,
) #close fluidpage
server <- function(input, output, session) {
output$testtab <- DT::renderDataTable({
tab <- data.frame(a = 1:10, b = 11:20, c = 21:30)
dat.tab <- datatable(tab) %>% formatPercentage('a', 0) %>%
formatCurrency(1:ncol(tab), '$')
return(dat.tab)
}) # close renderDataTable
} # close server
shinyApp(ui=ui, server=server)
Yielding this:
I want to create a Shiny gadget using miniUI which dynamically can add additional tabs to a miniTabstripPanel. However, no panels have shown up in my experiments when I try it using renderUI and uiOutput. I think it has to do with the height of the elements not being set correctly (by me).
Anyway, below is a minimal example. If I use the uiOutput() line, it does not work. If I instead comment that out and use the miniTabPanel() line directly, which is the exact code used in renderUI(), it works fine.
library(shiny)
library(miniUI)
TSTAddin <- function() {
panno <- 0
ui <- miniPage(
actionButton('btn_newPan', 'New Panel'),
miniTabstripPanel(
# miniTabPanel('pan1', miniContentPanel(height='100%', actionButton('Test','Test'))), miniTabPanel('pan2', miniContentPanel(height='100%', actionButton('Test','Test')))
uiOutput('panelset')
)
)
server <- function(input, output, session) {
output$panelset <- renderUI({
panno <<- panno+1
txt <- paste0("miniTabPanel('pan", 1:panno, "', miniContentPanel(height='100%', actionButton('Test','Test')))", collapse=", ")
list( eval(parse(text=txt)) )
})
}
viewer <- paneViewer(300)
runGadget(ui, server, viewer = viewer)
}
TSTAddin()
EDIT:
The code suggested by mkemp6 solves the problem. However, if I now include a button on the panel, only part of it is shown. How can one correct the size of the dynamically generated panels? An example adopting mkemp6's code follows.
library(shiny)
library(miniUI)
TSTAddin2 <- function() {
ui <- miniPage(
actionButton("nTabs", "More Tabs"),
actionButton("neg_nTabs", "Less Tabs"),
uiOutput('panelset')
)
server <- function(input, output, session) {
output$panelset <- renderUI({
n <- seq(max(input$nTabs - input$neg_nTabs + 1, 1))
miniTabList <- lapply(paste("Pan", n), function(x) miniTabPanel(x, actionButton('Test','Test')))
do.call(miniTabstripPanel, miniTabList)
})
}
viewer <- paneViewer(300)
runGadget(ui, server, viewer = viewer)
}
TSTAddin2()
Try this:
library(shiny)
library(miniUI)
TSTAddin <- function() {
ui <- miniPage(
actionButton("nTabs", "More Tabs"),
actionButton("neg_nTabs", "Less Tabs"),
uiOutput('panelset')
)
server <- function(input, output, session) {
output$panelset <- renderUI({
n <- seq(max(input$nTabs - input$neg_nTabs + 1, 1))
miniTabList <- lapply(paste("Pan", n), miniTabPanel)
do.call(miniTabstripPanel, miniTabList)
})
}
viewer <- paneViewer(300)
runGadget(ui, server, viewer = viewer)
}
TSTAddin()
Regarding your second issue with the size of the panels:
Whenever you use uiOutput(), shiny puts another div tag around the rendered content. As it appears, the style of this content is by default not compatible with the miniUI elements. However, this can be corrected by adding some specific CSS code (which I have basically copied from some other classes of miniUI.css).
Also, when you put several elements (in your case: action buttons) among each other within a miniContenPanel, it is advisable to create separate containers for each of them. You can easily do that using fillCol / fillRow as described in http://shiny.rstudio.com/articles/gadget-ui.html.
This code works with me (you may want to further improve the layout):
library(shiny)
library(miniUI)
TSTAddin2 <- function() {
ui <- miniPage(
tags$head(
tags$style(HTML("
.ui-output-mini {position: absolute;top:0;right:0;bottom:0;left:0;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;}
"))
),
fillCol(flex=c(NA, NA, 1),
actionButton("nTabs", "More Tabs", width='100%'),
actionButton("neg_nTabs", "Less Tabs", width='100%'),
uiOutput('panelset', class='ui-output-mini')
)
)
server <- function(input, output, session) {
output$panelset <- renderUI({
n <- seq(max(input$nTabs - input$neg_nTabs + 1, 1))
miniTabList <- lapply(paste("Pan", n), function(x) miniTabPanel(x, actionButton('Test','Test')))
do.call(miniTabstripPanel, miniTabList)
})
}
viewer <- paneViewer(300)
runGadget(ui, server, viewer = viewer)
}
TSTAddin2()