Output more than 1 datatables in shiny main panel - r

I have a shiny app that a user can check whether they want the data table displayed in the main panel. Depending on the numericinput, if they select 1, only 1 datatable be displayed or if they select 2 it will display 2 datatables I am not so sure how to code this in shiny R since I am new to this. Thank you for looking into this.
Here is my code
library("shiny")
df1 <- data.frame("2010-01"=double(),
"2010-02"=double(),
"2010-03"=double(),
"2010-04"=double()
)
df1<-rbind(df1,setNames(as.list(c(10,20,30,40)), names(df2)))
df2 <- data.frame("2010-01"=double(),
"2010-02"=double(),
"2010-03"=double(),
"2010-04"=double()
)
df2<-rbind(df2,setNames(as.list(c(100,200,300,400)), names(df2)))
df3 <- data.frame("2010-01"=double(),
"2010-02"=double(),
"2010-03"=double(),
"2010-04"=double()
)
df3<-rbind(df3,setNames(as.list(c(1000,2000,3000,4000)), names(df2)))
ui <-fluidPage(
sidebarPanel(
checkboxInput("add_data", "Add Data Table(s)"),
conditionalPanel(condition="input.add_data === true",
numericInput("numofdata",
label="Number of Data Table(s):",
min = 1,
max = 3,
value = 1,
step = 1),
uiOutput("num_of_data"),
textOutput("see_ranges")
),
actionButton("submit", "Submit")
),
mainPanel(
titlePanel("Output Data Table"),
DT::dataTableOutput("datatable.view", width = "95%")
) # end of main panel
)
server <- function(input, output, session) {
output$num_of_data <- renderUI({
lapply(1:input$numofdata, function(i) {
print(trend_list())
})
})
output$see_ranges <- renderPrint({
print(trend_list())
})
data.filter <- reactive({
df(i)
})
output$datatable.view <- DT::renderDataTable(
{
input$submit
if (input$submit==0) return()
isolate({
for(i in 1:input$numoftrends) {
datatable(data.filter(i),
rownames=FALSE,
extensions = c("FixedColumns", "FixedHeader", "Scroller"),
options = list(searching=FALSE,
autoWidth=TRUE,
rownames=FALSE,
scroller=TRUE,
scrollX=TRUE,
pagelength=1,
fixedHeader=TRUE,
class='cell-border stripe',
fixedColumns =
list(leftColumns=2,heightMatch='none')
)
)
}
})
})
}
shinyApp(ui = ui, server = server)

You should look at this article:
http://shiny.rstudio.com/gallery/creating-a-ui-from-a-loop.html
You will seen then that one has to create multiple renderDataTable instead of muliple datatable within one renderDataTable().
Also in your code you call df like a function df() but it is only defined as a variable.
See a generic running example below.
EDIT: Changed dynamic part of UI.
library(DT)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
selectInput("amountTable", "Amount Tables", 1:10, 3)
),
mainPanel(
# UI output
uiOutput("dt")
)
)
)
server <- function(input, output, session) {
observe({
lapply(1:input$amountTable, function(amtTable) {
output[[paste0('T', amtTable)]] <- DT::renderDataTable({
iris[1:amtTable, ]
})
})
})
output$dt <- renderUI({
tagList(lapply(1:input$amountTable, function(i) {
dataTableOutput(paste0('T', i))
}))
})
}
shinyApp(ui, server)

Related

Delete the row in DT table shiny

I am trying to delete the row in the table below but not able to . Can anyone please guide me here.
The row should get deleted when the user selects the row and then clicks on action button
library(shiny)
library(httr)
library(jsonlite)
library(readxl)
library(DT)
library(glue)
ui <- fluidPage({
au <- read_excel("au.xlsx")
au <- as.data.frame(au)
df <- reactiveValues(asd = NULL)
mainPanel(
dataTableOutput("ir"),
actionButton("ac", "ac")
)
})
server <- function(input, output, session) {
output$ir <- renderDataTable({
df$asd <- head(iris)
datatable(df$asd)
})
observeEvent(input$ac,{
# browser()
df$asd <- df$asd[-c(as.numeric(input$ir_rows_selected)),]
})
}
shinyApp(ui, server)
Here is the way using a Shiny button:
library(shiny)
library(DT)
ui <- fluidPage(
actionButton("delete", "Delete selected row"),
br(),
DTOutput("tbl")
)
server <- function(input, output, session){
output[["tbl"]] <- renderDT({
datatable(iris[1:5,],
callback = JS(c(
"$('#delete').on('click', function(){",
" table.rows('.selected').remove().draw();",
"});"
))
)
}, server = FALSE)
}
shinyApp(ui, server)
And here is the way using a button integrated in the DT table:
library(shiny)
library(DT)
ui <- fluidPage(
br(),
DTOutput("tbl")
)
server <- function(input, output, session){
output[["tbl"]] <- renderDT({
datatable(iris[1:5,],
extensions = 'Buttons',
options = list(
dom = 'Bfrtip',
buttons = list(
list(
extend = "collection",
text = "Delete selected row",
action = DT::JS(c(
"function ( e, dt, node, config ) {",
" dt.rows('.selected').remove().draw();",
"}"))
)
)
)
)
}, server = FALSE)
}
shinyApp(ui, server)
With these methods, the table is not re-rendered when the row is deleted.

updating table in Shiny

I've got a table that will initialize, but will not update. I use a few inputs, which then get called by a function to calculate the outputs. They will initialize with the correct values, but when I click the actionButton, nothing happens.
output$view<-renderTable({
tabSvol<-isolate(
data.frame(
S=c(
func1(input$in1),
func2(input$in2),
func3(input$in1,input$2)
)
)
)
tabSvol
})
Here's a MRE that allows you to add rows to a reactive table.
library(shiny)
library(tidyverse)
ui <- fluidPage(
numericInput("a", "A: ", value=NA),
selectInput("b", "B:", choices=c("X", "Y", "Z")),
actionButton("add", "Add row"),
tableOutput("table")
)
server <- function(input, output) {
rv <- reactiveValues(table=tibble(A=numeric(0), B=character(0)))
output$table <- renderTable({
rv$table
})
observeEvent(input$add, {
rv$table <- rv$table %>% add_row(A=input$a, B=input$b)
})
}
shinyApp(ui = ui, server = server)

Show a tabPanel in popup window or modalDialog

I need some help I want to show my reactive tabPanel in a popup with the shinyBS package.
Everything seems to work well except the creation of popup.
I am inspired by :
1) R Shiny - add tabPanel to tabsetPanel dynamically (with the use of renderUI)
2)Show dataTableOutput in modal in shiny app
My code :
library(shiny)
library(DT) # need datatables package
library(shinyBS)
ui <- shinyUI(fluidPage(
titlePanel("Example"),
sidebarLayout(
sidebarPanel(
selectInput("decision", label = "Choose your specie",
choices = iris$Species,
selected = "mtcars", multiple = TRUE)
),
mainPanel(
uiOutput('mytabs')
)
)
))
server <- shinyServer(function(input, output, session) {
output$mytabs <- renderUI({
nTabs = length(input$decision)
# create tabPanel with datatable in it
myTabs = lapply(seq_len(nTabs), function(i) {
tabPanel(paste0("dataset_", input$decision[i]),
tableOutput(paste0("datatable_",i))
)
})
do.call(tabsetPanel, myTabs)
})
# create datatables in popup ?
bsModal(
id = "modalExample",
"yb",
observe(
lapply(seq_len(length(input$decision)), function(i) {
output[[paste0("datatable_",i)]] <- renderTable({
as.data.frame(iris[iris$Species == input$decision[i], ])
})
})
)
)
})
shinyApp(ui, server)
Thanks in advance for any help !
bsModal is an UI element, so you need to put it into you UI. Within this modal you want to show the tabPanels (rendered via uiOutput), so all you need to do is to place your bsModal into the UI, and within this bsModal you have your uiOutput. All what is left is to add an actionButton which shows the modal.
library(shiny)
library(shinyBS)
ui <- shinyUI(fluidPage(
titlePanel("Example"),
sidebarLayout(
sidebarPanel(
selectInput("decision", label = "Choose your species",
choices = unique(iris$Species),
selected = unique(iris$Species), multiple = TRUE),
actionButton("show", "Show")
),
mainPanel(
bsModal("modalExample",
"myTitle",
"show",
uiOutput('mytabs')
)
)
)
))
server <- shinyServer(function(input, output, session) {
output$mytabs <- renderUI({
nTabs <- length(input$decision)
# create tabPanel with datatable in it
myTabs <- lapply(seq_len(nTabs), function(i) {
tabPanel(paste0("dataset_", input$decision[i]),
tableOutput(paste0("datatable_",i))
)
})
do.call(tabsetPanel, myTabs)
})
# create datatables in popup ?
observe(
lapply(seq_len(length(input$decision)), function(i) {
output[[paste0("datatable_",i)]] <- renderTable({
as.data.frame(iris[iris$Species == input$decision[i], ])
})
})
)
})
shinyApp(ui, server)
It's not clear to me what you want to do (maybe #thothal has the right answer). What about this app ?
library(shiny)
library(DT) # need datatables package
library(shinyBS)
ui <- shinyUI(fluidPage(
titlePanel("Example"),
sidebarLayout(
sidebarPanel(
selectInput("decision", label = "Choose your specie",
choices = iris$Species,
selected = "mtcars", multiple = TRUE),
actionButton("trigger_modal", "View modal")
),
mainPanel(
uiOutput("modal")
# uiOutput('mytabs')
)
)
))
server <- shinyServer(function(input, output, session) {
# output$mytabs <- renderUI({
# nTabs = length(input$decision)
# # create tabPanel with datatable in it
# myTabs = lapply(seq_len(nTabs), function(i) {
# tabPanel(paste0("dataset_", input$decision[i]),
# tableOutput(paste0("datatable_",i))
# )
# })
#
# do.call(tabsetPanel, myTabs)
# })
# create datatables in popup ?
observe(
lapply(seq_len(length(input$decision)), function(i) {
output[[paste0("datatable_",i)]] <- renderTable({
as.data.frame(iris[iris$Species == input$decision[i], ])
})
})
)
output$modal <- renderUI({
bsModal(
id = "modalExample",
"yb",
trigger = "trigger_modal",
do.call(tagList, lapply(seq_along(input$decision), function(i){
tableOutput(paste0("datatable_",i))
}))
)
})
})
shinyApp(ui, server)

data table disappear after editing in shiny app

I'm trying to make an editable and downloadable data table in shiny app. After I edit the table, the data table automatically disappear for some reason. This only happen when the data dat is reactive (which is necessary in my app).
Does anyone knows what is going on? Thanks a lot.
example code below:
library(shiny)
library(DT)
ui <- fluidPage(
selectInput("nrow",
"num of rows",
choices = 1:5,
selected = 3,
multiple = FALSE),
DTOutput("table")
)
server <- function(input, output){
dat = reactive({
iris[1:as.integer(input$nrow),]
})
output[["table"]] <- renderDT({
datatable(dat(), editable = "cell", extensions = "Buttons",
options = list(
dom = "Bfrtip",
buttons = list(
"csv"
)
))
})
observeEvent(input[["table_cell_edit"]], {
cellinfo <- input[["table_cell_edit"]]
dat() <<- editData(dat(), input[["table_cell_edit"]], "table")
})
}
shinyApp(ui, server)
Try this:
library(shiny)
library(DT)
ui <- fluidPage(
selectInput("nrow","num of rows",choices = 1:5,selected = 3,multiple = FALSE),
DTOutput("table")
)
server <- function(input, output){
v <- reactiveValues()
observeEvent(input$nrow,{
v$dat <- iris[1:as.integer(input$nrow),]
})
output[["table"]] <- renderDT({
datatable(v$dat, editable = "cell", extensions = "Buttons", options = list(dom = "Bfrtip",buttons = list("excel")))
})
observeEvent(input[["table_cell_edit"]], {
cellinfo <- input[["table_cell_edit"]]
v$dat <<- editData(v$dat, input[["table_cell_edit"]], "table")
})
}
shinyApp(ui, server)
Is it OK like this ? A possible unwanted behavior is that the table is reset after changing the number of rows. But I don't think we can avoid that... since these are two different tables.
library(shiny)
library(DT)
ui <- fluidPage(
selectInput("nrow",
"num of rows",
choices = 1:5,
selected = 3,
multiple = FALSE),
DTOutput("table")
)
server <- function(input, output){
dat0 <- iris
dat <- reactiveVal()
observe({
dat(dat0[1:as.integer(input$nrow),])
})
output[["table"]] <- renderDT({
datatable(dat(), editable = "cell", extensions = "Buttons",
options = list(
dom = "Bfrtip",
buttons = list(
"csv"
)
))
})
observeEvent(input[["table_cell_edit"]], {
cellinfo <- input[["table_cell_edit"]]
dat(editData(dat(), input[["table_cell_edit"]], "table"))
})
}
shinyApp(ui, server)

"empty data message" in renderTable

I user renderTable to show some data. However, sometimes the data table is empty, in which case I'd like to print "No data to show" or something similar. the default by renderTable is to show nothing for empty data. can this be changed? how?
You can use a condition into a renderUi to render either a message or a "tableOutput" (you can't render directly the table)
datas <- data.frame()
shiny::runApp(list(
ui = pageWithSidebar(
headerPanel("Example"),
sidebarPanel(
selectInput("dataset", "Dataset", choices = c("iris", "datas"))
),
mainPanel(
uiOutput("ui")
)
),
server = function(input, output, session) {
datasetInput <- reactive({
switch(input$dataset,
"iris" = iris,
"datas" = datas)
})
output$ui <- renderUI({
if(nrow(datasetInput()) == 0)
return("No data to show")
tableOutput("table")
})
output$table <- renderTable({
head(datasetInput())
})
}
))
I think you are looking for something like validate function.
Using example code provided by Julien:
datas <- data.frame()
shiny::runApp(list(
ui = pageWithSidebar(
headerPanel("Example"),
sidebarPanel(
selectInput("dataset", "Dataset", choices = c("iris", "datas"))
),
mainPanel(
tableOutput('table')
)
),
server = function(input, output, session) {
datasetInput <- reactive({
switch(input$dataset,
"iris" = iris,
"datas" = datas)
})
output$table <- renderTable({
y <- head(datasetInput())
validate(
need(nrow(y) > 0, "No Data to show")
)
y
})
}
))
If you still want to show a "table" within the UI, do this:
output$table_output <- renderTable {
data <- data.frame(a = c(1,2),
b = c(8,9)) #example data.frame
if (nrow(data) > 0) {
data
} else {
datatable(data.frame(Nachricht = "Die ausgewählte Schnittstelle enthält hierfür keine Daten."))
}
}

Resources