Search code examples
rshinyshinyapps

How to correctly download R script with Shiny Meta


I am currently working with shiny meta. I have a simple app that allows me to download a .csv calculate the row means of columns 2:length(data). (its a specific .csv). What I want is to be able to download a an Rscript of my code using shiny meta. Currently when I press download it gives me a .htm

I have no idea what is wrong with this.

Any help if appreciated!

library(shiny)
library(tidyverse)
library(DT)
library(shinymeta)

# Define UI for the app
ui <- fluidPage(
  
  # App title
  titlePanel("Calculate Grade"),
  
  # Sidebar with file input
  sidebarLayout(
    sidebarPanel(
      fileInput("file", "Upload CSV file"),
      downloadButton("download", "Download Results"),
      downloadButton("meta", "download R code")
    ),
    
    # Main panel with table output
    mainPanel(
      verbatimTextOutput("code"),
      DT::dataTableOutput("table")
    )
  )
)

# Define server logic
server <- function(input, output) {
  
  # Read uploaded file
  data <- metaReactive({
    req(..(input$file))
    read.csv(..(input$file$datapath))
  })
  
  # Calculate means of each row
  means <- metaReactive({
    ..(data()) %>%
      rowwise() %>%
      mutate(mean = mean(c_across(2:length(..(data())))))
  })
  
  # Output data table with means
  output$table <- metaRender(renderDataTable, {
    ..(means())
  })
  
  # Download results as CSV
  output$download <- downloadHandler(
    filename = function() {
      paste("means_", Sys.Date(), ".csv", sep = "")
    },
    content = function(file) {
      write.csv(means(), file, row.names = FALSE)
    }
  )
output$code <- renderPrint({
  expandChain(quote(library(tidyverse)), output$table())
})

output$download <- downloadHandler(
  filename = "report.zip",
  content = function(file) {
    report <- expandChain(output$table()
    )
    buildScriptBundle(report, file)
  }
)

}

# Run the app
shinyApp(ui, server)

Currently when I press the Download button for meta it gives back an .htm which is useless...


Solution

  • The shinymeta package is a niche one but very important in my opinion. The code reproducibility in the shiny apps is a very valuable addition.

    I see many problems with your app like the duplicated output id's and usage of metaReactive where you need the metaReactive2 function. With metaReactive2, you can use metaExpr to select specific parts of the code needed for reproducibility so e.g., req(input) can be skipped.

    You did not provide the data so I use the write.csv(airquality, "airquality.csv") as an example dataset.

    library(shiny)
    library(tidyverse)
    library(DT)
    library(shinymeta)
    
    # Define UI for the app
    ui <- fluidPage(
      # App title
      titlePanel("Calculate Grade"),
    
      # Sidebar with file input
      sidebarLayout(
        sidebarPanel(
          fileInput("file", "Upload CSV file"),
          downloadButton("download", "Download Results"),
          downloadButton("downloadr", "download R code")
        ),
    
        # Main panel with table output
        mainPanel(
          verbatimTextOutput("code"),
          DT::dataTableOutput("table")
        )
      )
    )
    
    # Define server logic
    server <- function(input, output) {
      # Read uploaded file
      data <- metaReactive2({
        shiny::req(input$file)
        metaExpr({
          read.csv(..(input$file$datapath))
        })
      })
    
      # Calculate means of each row
      means <- metaReactive({
        ..(data()) |>
          rowwise() |>
          mutate(mean = mean(c_across(2:ncol(..(data())))))
      })
    
      # Output data table with means
      output$table <- metaRender(renderDataTable, {
        ..(means())
      })
    
      # Download results as CSV
      output$download <- downloadHandler(
        filename = function() {
          paste("means_", Sys.Date(), ".csv", sep = "")
        },
        content = function(file) {
          write.csv(means(), file, row.names = FALSE)
        }
      )
    
      output$code <- renderPrint({
        expandChain(quote(library(tidyverse)), output$table())
      })
    
      output$downloadr <- downloadHandler(
        filename = "report.zip",
        content = function(file) {
          report <- output$code()
          buildScriptBundle(report, file)
        }
      )
    }
    
    # Run the app
    shinyApp(ui, server)
    

    enter image description here