How to Create Shiny R Dynamic Rendertable, with a Number of Tables Determined by The Uploaded CSV Files

How to create Shiny R dynamic renderTable, with a number of tables determined by the uploaded CSV files?

A solution is to put everything inside an observe.

library(shiny)

ui <- fluidPage(
fluidRow(column(3,
wellPanel(
fileInput(
inputId = "files",
label = "Choose cvs files",
accept = c('text/csv',
'text/comma-separated-values,text/plain',
'.csv'),
multiple = TRUE
)
)),
column(5, offset = 1, uiOutput("tables"))))

server <- function(input, output) {
observe({
if (!is.null(input$files)) {
max_table = length(input$files[, 1])

lst <- list()
for (i in 1:length(input$files[, 1])) {
lst[[i]] <-
read.csv(
input$files[[i, 'datapath']],
sep = ",",
header = TRUE,
skip = 4,
dec = "."
)
}

output$tables <- renderUI({
plot_output_list <- lapply(1:max_table, function(i) {
tablename <- paste("tablename", i, sep = "")
tableOutput(tablename)
})
do.call(tagList, plot_output_list)
})

for (i in 1:max_table) {
local({
my_i <- i
tablename <- paste("tablename", my_i, sep = "")
output[[tablename]] <- renderTable({
lst[[my_i]]
})
})
}
}
})

}

shinyApp(ui = ui, server = server)

How to upload multiple tables and display them separately in r shiny?

Here is an example that may be helpful:

https://stackoverflow.com/a/35943224/3460670

Edit: Try this for your server for creating N tables. You can read in your N data files in a list, and dynamically create outputs for the N tables in an observe expression.

server <- function(input, output) {

observe({
if (!is.null(input$calfile)) {
N_tables = length(input$calfile[, 1])

upload <- list()
for (i in 1:N_tables) {
upload[[i]] <- read.csv(input$calfile$datapath[i])
}

output$contents <- renderUI({
table_output_list <- lapply(1:N_tables, function(i) {
tableOutput(paste0("table_name", i))
})
do.call(tagList, table_output_list)
})

for (i in 1:N_tables) {
local({
my_i <- i
output[[paste0("table_name", my_i)]] <- renderTable({
upload[[my_i]]
})
})
}
}
})

}

Dynamically Creating Images And Tables From User Input In R Shiny

I would approach this by wrapping essentially all of what you're doing in an observeEvent function. I don't think reactive are the natural way to try to get your functions to run since they're more about returning an R object output that runs when required.

Something like:

observeEvent(input$dis,
{
Snapshot <- CreateSnapshot(input$dis)

VisualizationTable <- ProduceTable(input$dis)

fileData <- your read function of choice since it no longer needs to be reactive

output$fileData <- renderTable({
fileData
})

etc..

}
)

So every time the user chooses a discipline the entire thing will run, generating the outputs you want.

If there's no reason you want to produce a csv you could streamline this more by not saving the csv since you save it only to read the file to load it.

R+Shiny: read file and use its content

This code loads the file straight into the output table and doesn't really store the raw table anywhere. This snippet of code is actually loading the file:

    df <- read.csv(input$file1$datapath,
header = input$header,
sep = input$sep,
quote = input$quote)

You can use this outside of the renderTable({}) to load the file just as a normal variable and do whatever you want with it.

However, if you set this code straight into the server function, it won't work - since this is a user input, you should set this variable as reactive, so I would do something like this:

  df = reactive({
req(input$file1)

df <- read.csv(input$file1$datapath,
header = input$header,
sep = input$sep,
quote = input$quote)

return(df)
})

Then you can call df() and do whatever you want with it. Ofc it would be nice to add try statements or some checks to make sure the file can be loaded properly, like the in the renderTable({}).

So the server side should look like this:

server <- function(input, output) {

df = reactive({
req(input$file1)

df <- read.csv(input$file1$datapath,
header = input$header,
sep = input$sep,
quote = input$quote)

return(df)
})

output$contents <- renderTable({

# input$file1 will be NULL initially. After the user selects
# and uploads a file, head of that data file by default,
# or all rows if selected, will be shown.

req(input$file1)

# when reading semicolon separated files,
# having a comma separator causes `read.csv` to error
tryCatch(
{
df <- read.csv(input$file1$datapath,
header = input$header,
sep = input$sep,
quote = input$quote)
},
error = function(e) {
# return a safeError if a parsing error occurs
stop(safeError(e))
}
)

if(input$disp == "head") {
return(head(df))
}
else {
return(df)
}

})

}

How to track the net number of action button clicks in order to correctly label a series of rendered tables with their count?

We need another obersver to modify the colnames in uiTbl1. Please check the following:

library(shiny)
library(rhandsontable)

data1 <- data.frame(row.names = c("A","B","C","Sum"),"Col 1"=c(1,1,0,2),check.names=FALSE)

ui <- fluidPage(
br(),
actionButton("addTbl","Add table"),
br(),br(),
tags$div(id = "placeholder",
tags$div(
style = "display: inline-block",
rHandsontableOutput("hottable1")
)
)
)

server <- function(input, output, session) {
uiTbl <- reactiveValues(div_01_tbl = data1)
rv <- reactiveValues()

observeEvent(input$hottable1, {uiTbl$div_01_tbl <- hot_to_r(input$hottable1)})

output$hottable1 <- renderRHandsontable({rhandsontable(uiTbl$div_01_tbl, useTypes = TRUE)})

observeEvent(input$addTbl, {
# divID <- gsub("\\.", "", format(Sys.time(), "%H%M%OS3")) # system time at add used as table ID
divID <- paste0("div_", sprintf("%02d", input$addTbl+1))
dtID <- paste0(divID, "_DT")
btnID <- paste0(divID, "_rmv")
uiTbl[[paste0(divID,"_tbl")]] <- data1 # captures initial dataframe values

insertUI(
selector = "#placeholder",
ui = tags$div(
id = divID,
style = "display:inline-block;",
rHandsontableOutput(dtID),
actionButton(btnID, "Delete", class = "pull-left btn btn-danger"),
)
)

output[[dtID]] <- renderRHandsontable({
req(uiTbl[[paste0(divID,"_tbl")]])
rhandsontable(uiTbl[[paste0(divID,"_tbl")]], useTypes = TRUE)
})

observeEvent(input[[dtID]], {uiTbl[[paste0(divID,"_tbl")]] <- hot_to_r(input[[dtID]])})

observeEvent(input[[btnID]],{
removeUI(selector = paste0("#", divID))
rv[[divID]] <- NULL
uiTbl[[paste0(divID,"_tbl")]] <- NULL
},
ignoreInit = TRUE,
once = TRUE
)
})

observe({
tables_list <- reactiveValuesToList(uiTbl)
tables_list <- tables_list[order(names(tables_list))]
table_lengths <- lengths(tables_list)
cumsum_table_lengths <- cumsum(table_lengths)[table_lengths != 0L]

for(i in seq_along(cumsum_table_lengths)){
names(uiTbl[[names(cumsum_table_lengths[i])]]) <- paste("Col", cumsum_table_lengths[i])
}
})
}

shinyApp(ui, server)

result

Shiny R renderPlots on the fly

If anyone's still interested in an answer, try this:

library(shiny)

runApp(shinyApp(

ui = shinyUI(
fluidPage(
numericInput("number", label = NULL, value = 1, step = 1, min = 1),
uiOutput("plots")
)
),

server = function(input, output) {

### This is the function to break the whole data into different blocks for each page
plotInput <- reactive({
n_plot <- input$number
total_data <- lapply(1:n_plot, function(i){rnorm(500)})
return (list("n_plot"=n_plot, "total_data"=total_data))
})

##### Create divs######
output$plots <- renderUI({
plot_output_list <- lapply(1:plotInput()$n_plot, function(i) {
plotname <- paste("plot", i, sep="")
plotOutput(plotname, height = 280, width = 250)
})
do.call(tagList, plot_output_list)
})

observe({
lapply(1:plotInput()$n_plot, function(i){
output[[paste("plot", i, sep="") ]] <- renderPlot({
hist(plotInput()$total_data[[i]], main = paste("Histogram Nr", i))
})
})
})
}

))


Related Topics



Leave a reply



Submit