I am fairly new to R markdown. I have built an app that requires the user to provide multiple inputs to generate a table, which can then be saved locally.
I have been now asked to implement a sort of report to list all the variables inserted by the user (in a sort of formatted document), so that before generating the table one can review all the settings and change them in case of errors.
To avoid major UI restructure, I thought about using a r markdown document and visualize it inside a modal. My problem is that rmarkdown::render renders to an output, while bs_modal takes for the argument body a character (HTML) variable.
Is there a way to make this work? Or are there better way to accomplish this?
A minimal example:
my .Rmd
---
title: "Dynamic report"
output:
html_document: default
pdf_document: default
params:
n : NA
---
A plot of `r params$n` random points.
```{r, echo=FALSE}
plot(rnorm(params$n), rnorm(params$n))
```
My App.R
library(shiny)
library(bsplus)
library(rmarkdown)
shinyApp(
ui = fluidPage(
selectInput(
inputId = "numb",
label = "Label with modal help",
choices = 50:100
),
actionButton(inputId = "mysheet",
label = "Open modal") %>% bs_attach_modal(id_modal = "modal1"),
textOutput("result")
),
server = function(input, output) {
observeEvent(input$mysheet, {
params <- input$numb
md_out <-
rmarkdown::render(
"report.Rmd",
params = params,
envir = new.env(parent = globalenv())
)
bs_modal(
id = "modal1",
title = "Equations",
body = md_out,
size = "medium"
)
})
output$result <- renderText({
paste("You chose:", input$numb)
})
}
)
bs_modal does not work like this, it must be in the UI. Below is a solution using the classical Shiny modal, no bsplus or other package.
library(shiny)
shinyApp(
ui = fluidPage(
selectInput(
inputId = "numb",
label = "Label with modal help",
choices = 50:100
),
actionButton(inputId = "mysheet",
label = "Open modal"),
textOutput("result")
),
server = function(input, output) {
observeEvent(input$mysheet, {
params <- list(n = input$numb)
md_out <-
rmarkdown::render(
"report.Rmd",
params = params,
envir = new.env(parent = globalenv())
)
showModal(modalDialog(
includeHTML(md_out),
title = "Equations",
size = "m"
))
})
output$result <- renderText({
paste("You chose:", input$numb)
})
}
)
Use html_fragment as the Rmd output:
---
title: "Dynamic report"
output:
html_fragment
params:
n : NA
---
A plot of `r params$n` random points.
```{r, echo=FALSE}
plot(rnorm(params$n), rnorm(params$n))
```
Related
In my toy example, I am trying to render Rmd file in the shiny app while passing a variable from Shiny to Rmd. Somehow, the Rmd file is not able to pick the input input$selectInput passed to Rmd file. Can someone show me how to pass a variable from Shiny to Rmd file and print it there?
My intent is to use Rmd file as a template which will be filled by variables from Shiny App at runtime. There may be better alternatives to this approach to render HTML templates in Shiny, do let me know if you know any better approches.
library(shiny)
library(shinydashboard)
library(knitr)
sidebar <- dashboardSidebar(
collapsed = FALSE,
sidebarMenu(
id = "menu_sidebar",
conditionalPanel(
condition = "input.main_tab == 'tab 1'",
selectizeInput(inputId = "selectInput", label = "Choose an option", choices = c("a", "b", "c"), selected = "a", multiple = FALSE),
radioButtons(inputId = "buttons", label = "Choose one:",
choices=c(
"A" = "a",
"B" = "b"))
)
)
)
body <- dashboardBody(
fluidRow(
tabsetPanel(
id = "main_tab",
selected = "tab 1",
tabPanel(title = "tab 1", "Tab content 1",
conditionalPanel("input.buttons == 'a'",
{
knit("text1.Rmd", envir = globalenv(), quiet = T)
withMathJax(includeMarkdown("text1.md"))
},
tags$style("html, body {overflow: visible !important;")),
conditionalPanel("input.buttons == 'b'", htmlOutput("plot_overview_handler"))
)
)
)
)
shinyApp(
ui = dashboardPage(
dashboardHeader(title = "tabBoxes"),
sidebar,
body
),
server = function(input, output) {
output$tabset1Selected <- output$tabset2Selected <- renderText({
input$main_tab
})
output$plot_overview_handler <- renderUI({
pars <- list(variable_1 = input$selectInput)
includeMarkdown(rmarkdown::render(input = "text2.Rmd",
output_format = "html_document",
params = pars,
run_pandoc = FALSE,
quiet = TRUE,
envir = new.env(parent = globalenv())))
})
}
)
Rmd File 1 - text1.Rmd
---
title: "tst2"
output: html_document
runtime: shiny
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
#``` # Uncomment this to run code
## R Markdown
```{r cars}
print(input$selectInput)
#``` # Uncomment this to run code
Rmd File 2 - text2.Rmd
---
title: "tst2"
output: html_document
runtime: shiny
params:
variable_1: NA
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
#``` # Uncomment this to run code
## R Markdown
```{r cars}
print(params$variable_1)
#``` # Uncomment this to run code
I am trying to adapt the RMarkdown file with *.rmd extension into Shiny application. My file has elements of Shiny but works with flexdashboard. Below you can see the code.
---
title: "Test"
author: " "
output:
flexdashboard::flex_dashboard:
orientation: columns
social: menu
source_code: embed
runtime: shiny
editor_options:
markdown:
wrap: 72
---
# Module 1
```{r global, include=FALSE}
library(biclust)
data(BicatYeast)
set.seed(1)
res <- biclust(BicatYeast, method=BCPlaid(), verbose=FALSE)
```
## Inputs {.sidebar}
```{r}
selectInput("clusterNum", label = h3("Cluster number"),
choices = list("1" = 1, "2" = 2),
selected = 1)
```
## Row {.tabset}
### Parallel Coordinates
```{r}
num <- reactive(as.integer(input$clusterNum))
renderPlot(
parallelCoordinates(BicatYeast, res, number=num()))
```
### Data for Selected Cluster
```{r}
renderTable(
BicatYeast[which(res#RowxNumber[, num()]), which(res#NumberxCol[num(), ])]
)
```
The shiny app usually has two main parts first is ui and second is server, so can anybody help how to solve this problem and run this file as a Shiny app.
library(shiny)
library(biclust)
ui <- fluidPage(
selectInput("clusterNum",
label = h3("Cluster number"),
choices = list("1" = 1, "2" = 2),
selected = 1
),
plotOutput("plot"),
tableOutput("table")
)
server <- function(input, output, session) {
set.seed(1)
data(BicatYeast)
res <- biclust(BicatYeast, method = BCPlaid(), verbose = FALSE)
num <- reactive(as.integer(input$clusterNum))
output$plot <-
renderPlot(
parallelCoordinates(BicatYeast, res, number = num())
)
output$table <-
renderTable(
BicatYeast[which(res#RowxNumber[, num()]), which(res#NumberxCol[num(), ])]
)
}
shinyApp(ui, server)
I want to output Shiny app as a PDF report. But R Markdown gives the following error "Warning: Error in eval: object 'plot2' not found".
The plot works in Shiny, I'm not too familiar with Markdown and I'm getting really frustrated since I feel like I have tried quite a few potential solutions. What am I doing wrong?
Shiny UI
library(ggplot2)
library(tidyr)
library(DBI)
library(RODBCext)
library(shiny)
library(knitr)
library(kableExtra)
ui <- fluidPage(
pageWithSidebar(
headerPanel(""),
sidebarPanel(
textInput("Table", ""),
downloadButton("downloadData", "Download"),
submitButton(text="Submit"),
mainPanel(
tabsetPanel(
tabPanel("Data", tableOutput("tTable"))
),
tabsetPanel(
tabPanel("Graph", plotOutput("plot1")
)
)
)
Shiney Server
server <- function(input, output, session)
{
SQLData <- reactive({
#SQL Query
})
output$tTable <- renderTable(SQLData())
output$plot1 <- renderPlot({
da <- gather(SQLData(), key=Result, 'Control', 'Sample'
)
da2 <- data.frame(da)
ggplot(da2,aes(x=Result,y=Control, color=Result))+geom_point(size = 5) + scale_y_continuous(limits = c(80, 120)) +labs(y="", x = "")})
output$downloadData <- downloadHandler(
filename = "report.pdf",
content = function(file)
{ params <- list(table = SQLData(),
plot2 = {
da <- gather(SQLData(), key=Result, 'Control', 'Sample'
)
da2 <- data.frame(da)
ggplot(da2,aes(x=Result,y=Control, color=Result))+geom_point(size = 5) + scale_y_continuous(limits = c(80, 120)) +labs(y="", x = "")})}
)
rmarkdown::render(input = "Report.Rmd",
output_file = file,
params = params,
envir = new.env(parent = globalenv())
)
}
)
}
shinyApp(ui = ui, server = server)
R Markdown Report
---
title: "Report"
output: pdf_document
header-includes:
- \usepackage{float}
- \usepackage{booktabs}
- \usepackage{makecell}
params:
table: NA
plot2: NA
---
```{r echo = FALSE, eval = TRUE}
kable(params$table, format="latex", booktabs=TRUE) %>%
kable_styling(latex_options="scale_down")
```{r echo = FALSE, eval = TRUE}
library(ggplot2)
print(plot2)
I'm trying to create an Rmarkdown that displays different amounts of text based on user input into a shiny application. I've made an basic example below. There are 2 text inputs and a checkbox. If the checkbox is false only the 1st text box value is printed to the markdown. If the checkbox is true then both values are printed. I want the output for both text boxes to appear like the 1st textbox output.
Ui:
library(shiny)
library(shinyjs)
ui <- fluidPage(
titlePanel("Hello Shiny!"),
sidebarLayout(
sidebarPanel(
textInput(inputId = "text1",
label = "1st text", value = "1st text"),
checkboxInput(inputId = "checkBox", label = "Checkbox"),
textInput(inputId = "input2",
label = "2nd text", value = "2nd text"),
downloadButton("download", "Download button")
),
mainPanel(
verbatimTextOutput("checkBoxValue")
)
)
)
Server:
library(shiny)
library(shinyjs)
server <- function(input, output) {
output$checkBoxValue <- renderText(input$checkBox)
Text1Value <- reactive({input$text1})
BoxValue<- reactive(input$checkBox)
Input2Value <- reactive({input$input2})
output$download <- downloadHandler(
filename = "Test.docx",
content = function(file) {
tempReport <- file.path(tempdir(), "TestRMD.Rmd")
file.copy("TestRMD.Rmd", tempReport, overwrite = TRUE)
params = list(
Text1Value = Text1Value(),
BoxValue = BoxValue(),
Input2Value = Input2Value()
)
rmarkdown::render(
tempReport,
output_file = file,
params = params,
envir = new.env(parent = globalenv()),
quiet = FALSE
)
})
}
Rmarkdown:
---
title: "Test"
output: word_document
params:
Text1Value: NA
BoxValue: NA
Input2Value: NA
---
```{r echo= FALSE, message = FALSE, include = FALSE}
library(shiny)
library(knitr)
library(latex2exp)
Text1Value<- params$Text1Value
BoxValue<- params$BoxValue
Input2Value<- params$Input2Value
```
# Value for text 1 is `r Text1Value`
```{r, echo=FALSE}
if(BoxValue == TRUE){
"Value for input 2 is `r Input2Value`"
}
```
Currently I can get the text from the second text output to appear conditionally, however it renders looking like R code. I want it to appear in the same format as the output for the 1st text input.
How would I accomplish this?
The the following in your Rmd file. You already are in a code block and don't need to have additional inline r formatting. You can use results = 'asis' in your block and also add the header (#) for identical formatting if you'd like:
```{r, echo=FALSE, results='asis'}
if(BoxValue == TRUE){
cat("# Value for input 2 is", Input2Value)
}
```
I am trying to create a shiny application that allows users to enter text and upload an image. I would then like the text inputted by the user and image uploaded by the user to be downloaded as an html report in a similar format only with the headings, text, and image. My aim is to have multiple text boxes and associated images in a report that is downloaded.
I have the following code:
library(shiny)
library(rmarkdown)
ui <-
fluidPage(
titlePanel("QA Template"),
sidebarLayout(
sidebarPanel(
radioButtons('format', 'Document format', c('HTML'),
inline = TRUE),
downloadButton('downloadReport')
)),
mainPanel(
fluidRow(
h2("Presentation"),
column(5,h4("Titles"),
textAreaInput("inText", "Do titles properly convey
content?",height='100px',width='400px')),
column(1,h4("Upload Image"),
fileInput("file1",label="",
accept = c('image/png', 'image/jpeg','image/jpg')
)),
column(4,offset = 1,imageOutput('p1')))))
server <- function(input, output, session) {
inText<-reactive({textAreaInput()})
output$inText<-renderText({textAreaInput()})
file1 <- reactive({gsub("\\\\", "/", input$file1$datapath)})
output$p1<-renderImage({list(src = file1())})
downloadHandler(
filename =
paste("QA_report","file",".html",sep=""),
content = function(file) {
tempReport<-file.path(tempdir(),"QA_report.Rmd")
file.copy('QA_report.Rmd', tempReport,overwrite = TRUE)
##Parameters to pass
params <- list(text1=inText,pic1=file1)
rmarkdown::render(tempReport,output_file=file, params=params,
envir = new.env(parent = globalenv()))
}
)
}
shinyApp(ui = ui, server = server)
I also have this in the .Rmd:
---
title: "QA Template"
output: html_document
params:
text1: NA
pic1: NA
---
```{r include=FALSE}
library(knitr)
```
### Presentation
## Titles
# Do titles properly convey content?
```{r, results='asis',echo=FALSE,warning=FALSE}
print(params[["text1"]])
```
```{r, results='asis',echo=FALSE,warning=FALSE}
knitr::include_graphics(params[["pic1"]])
```
There is a small quirk with using renderImage() we need to set the deleteFile flag to FALSE. Otherwise, the file is read into the temp directory, displayed for the user and then deleted.
Not sure what you were trying to do here but it looks wrong textAreaInput is a UI function. You need to refer to the text flowing into the server with input$inText not output$inText or textAreaInput()
inText<-reactive({textAreaInput()})
output$inText<-renderText({textAreaInput()})
Here is the working code,
library(shiny)
library(rmarkdown)
ui <-fluidPage(
titlePanel("QA Template"),
sidebarLayout(
sidebarPanel(
radioButtons('format', 'Document format', c('HTML'),
inline = TRUE),
downloadButton('downloadReport')
),
mainPanel(
fluidRow(
h2("Presentation"),
column(5,h4("Titles"),
textAreaInput("inText", "Do titles properly convey
content?",height='100px',width='400px')),
column(1,h4("Upload Image"),
fileInput("file1",label="",
accept = c('image/png', 'image/jpeg','image/jpg')
)),
column(4,offset = 1,imageOutput('p1'))
)
)
)
)
server <- function(input, output, session) {
file1 <- reactive({gsub("\\\\", "/", input$file1$datapath)})
output$p1<-renderImage({
req(file1())
browser()
list(src = file1())
},deleteFile = FALSE)
output$downloadReport <- downloadHandler(
filename =
paste("QA_report","file",".html",sep=""),
content = function(file) {
tempReport<-file.path(tempdir(),"QA_report.Rmd")
file.copy('QA_report.Rmd', tempReport,overwrite = TRUE)
##Parameters to pass
params <- list(text1=input$inText,pic1=file1())
rmarkdown::render(tempReport,output_file=file, params=params,
envir = new.env(parent = globalenv()))
}
)
}
shinyApp(ui = ui, server = server)