R shiny - User editable text input from UI - r

Below logic gives Dropdown's from UI and working well.
dynamic textInput with R shiny ( USer can enter any text )
Need Help: Now I want user input STRING on "col_a4" to match user input string rather then drop down on"col_a4".
Used shiny dashboard and DT library in my work. Is there any way i can include search option in UI to search in the -col_a4
###### UI.R
library(shiny)
library(shinydashboard)
library(DT)
ui <- shinyUI(fluidPage(titlePanel("Demo"),selectInput("dataset", "Choose a dataset:",choices = c("Book1", "Book2", "Book3")),
column(width=2,uiOutput("col_a1")),
column(width=2,uiOutput("col_a2")),
column(width=2,uiOutput("col_a3")),
column(width=2,uiOutput("col_a4")),
div(style="display: inline-block;vertical-align:top; width: 8px;",HTML("<br>")),
downloadButton("downloadData", "Click Me"),
uiOutput("dt")
))
###### server.R
library(shiny)
library(DT)
server = shinyServer(function(input,output){
global <- reactiveValues(refresh = FALSE)
datasetInput <- reactive({
switch(input$dataset,
"Book1" = Book1,
"Book2" = Book2,
"Book3" = Book3)
})
output$Dataset1 <- renderDataTable({
data=datasetInput()
})
output$col_a1 = renderUI({
selectInput("col_a1", "Select col_a1:", datasetInput()$col_a1,selectize = TRUE,multiple = T)
})
output$col_a2 = renderUI({
selectInput("col_a2", "Select col_a2:", datasetInput()$col_a2,selectize = TRUE,multiple = T)
})
output$col_a3 = renderUI({
selectInput("col_a3", "Select col_a3:", datasetInput()$col_a3,selectize = TRUE,multiple = T)
})
output$col_a4 = renderUI({
selectInput("col_a4", "Select col_a4:", datasetInput()$col_a4,selectize = TRUE,multiple = T)
})
output$Counter = renderText(
{
output$Clicked = renderText(0)
isolate(global$refresh <- FALSE)
filter = datasetInput()$col_a1%in%input$col_a1 &
datasetInput()$col_a2%in%input$col_a2 &
datasetInput()$col_a3%in%input$col_a3 &
datasetInput()$col_a4%in%input$col_a4
DataFilter1 = paste("Total Number of Records",nrow(subset(datasetInput(),
filter)))
}
)
observeEvent(input$Click,{
output$Clicked = renderText(1)
isolate(global$refresh <- TRUE)
output$Table = DT::renderDataTable(
{
input$Click
filter = datasetInput()$col_a1%in%input$col_a1 &
datasetInput()$col_a2%in%input$col_a2 &
datasetInput()$col_a3%in%input$col_a3 &
datasetInput()$col_a4%in%input$col_a4
DataFilter = subset(datasetInput(),filter)
})
output$Datasetaa1 <- renderDataTable({
data=Table()
})
output$mytable11 <- DT::renderDataTable({
DT::datatable(Datasetaa1[, input$show_vars, drop = FALSE])
})
output$dt <- renderUI({if(global$refresh == FALSE) return()
dataTableOutput('mytable11')})
})
myout = reactive({
filter = datasetInput()$col_a1%in%input$col_a1 &
datasetInput()$col_a2%in%input$col_a2 &
datasetInput()$col_a3%in%input$col_a3 &
datasetInput()$col_a4%in%input$col_a4
DataFilter = subset(datasetInput(),filter)
})
output$downloadData <- downloadHandler(
filename=function() {
paste('data-', Sys.Date(), '.csv', sep='')
},
content = function(file) {
write.csv(myout(),file)
},
contentType = "text/plain"
)
})

Related

How can I put the conditional while rendering the datatable in rshiny

I am trying to achieve following steps while working on the rshiny :
1: creating dynamic tabs on click of the cell : DONE
2: creating dynamic subtabs on click of the parent tab : DONE
3: need to render the datatable based on the following condition :
if ( are matching or == ) then display the data accordingly.
please find the below code for your reference :
library(shiny)
library(DT)
library(shinyWidgets)
shinyApp(
ui <- fluidPage(
headerPanel("Product Details"),
mainPanel(
# Output: Tabset w/ plot, summary, and table ----
tabsetPanel(type = "tabs", id="myTabs",
tabPanel("Company Details", DT::dataTableOutput("data")),
)
)
),
server <- function(input, output, session) {
readXLSXFile <- readxl::read_excel(paste("sample_data.xlsx"),1)
data <- head(readXLSXFile)
tabIndex <- reactiveVal(0)
myValue <- reactiveValues(companyDetails = '')
shinyInput <- function(FUN, len, id, ...) {
inputs <- character(len)
for (i in seq_len(len)) {
inputs[i] <- as.character(FUN(paste0(id, i), ...))
}
inputs
}
df <- reactiveValues(data = data.frame(
DealID = data[1],
Details = shinyInput(actionButton, length(data)+1,
'button_', label = "Edit",
onclick = 'Shiny.onInputChange(\"select_button\", this.id)',
style = "color: black;
background-color: white",
class="btn-success",
#icon = icon("edit")
),
Tickers = data[3],
stringsAsFactors = FALSE
# row.names = 1:length(data)
))
output$data <- DT::renderDataTable(
df$data, server = FALSE, escape = FALSE, selection = 'none'
)
observeEvent(input$select_button, {
selectedRow <- as.numeric(strsplit(input$select_button, "_")[[1]][2])
myValue$companyDetails <<- paste('click on ',df$data[selectedRow,1])
stringVal <- c(unlist(strsplit(df$data[selectedRow,3],",")))
topTabValue <- c(df$data[selectedRow,1])
subTabData <- c()
datafromsecondRow <- c(data[2][1])
subTabDataOutput <- c()
data_frame_mod <- c()
appendTab("myTabs",
tabPanel(topTabValue,br(),
actionButton("removeTab", "Remove this Tab", icon = icon("remove")),br(),br(),
tabsetPanel(type="tabs", id=c(topTabValue)
),
),
# select=TRUE
)
lapply(1:length(stringVal), function(i) {
subTabData = stringVal[i]
readXLSXFileSheetTwo <- readxl::read_excel(paste("sample_data.xlsx"),2)
dataFileTwo <- head(readXLSXFileSheetTwo)
# print(c(dataFileTwo$Ticker) %in% c(subTabData))
# print("+++++++++++++++++++")
# print(subTabData)
appendTab(c(topTabValue),
tabPanel(subTabData, br(),
tags$h5(paste("You are at -> ",subTabData)),
output$subTabData <- DT::renderDataTable({
dataFileTwo[c(dataFileTwo$Ticker) %in% c(subTabData),TRUE]
datatable(dataFileTwo, options = list(dom = 'ft'),escape=FALSE)
})
),
# print(c(subTabData))
)
observeEvent(input$subTabData, {
appendTab(subTabData,
tabPanel(topTabValue,br(),
actionButton("removeTab", "Remove this Tab", icon = icon("remove")),br(),br(),
tabsetPanel(type="tabs", id=c(topTabValue)
),
),
)
})
})
})
observeEvent(input$removeTab, {
removeTab("myTabs", target=input$myTabs)
})
output$myText <- renderText({
myValue$companyDetails
})
}
)
Please help me to solve this point.
output$subTabData <- DT::renderDataTable({
**dataFileTwo[c(dataFileTwo$Ticker) %in% c(subTabData),TRUE]**
datatable(dataFileTwo, options = list(dom = 'ft'),escape=FALSE)
})
It is still rendering the whole dataset.. I stuck on conditional render the data on click of subtab.

CheckboxInput with Edit table in DT R Shiny

I tried to combine editing table by adding, deleting row in DT table with checkboxInput(). It is not quite correct.
If I didn't add editing feature, it returned correct, but if I added editing feature,it didn't response after I added another row. I got stuck for a while, I will appreciate any help from you guys
library(shiny)
library(shinyjs)
library(DT)
# Tab 2 UI code.
tab2UI <- function(id) {
ns <- NS(id)
tabPanel(
"Tab 2",
fluidRow(
#uiOutput(ns('cars')),
h2('The mtcars data'),
DT::dataTableOutput(ns('mytable2')),
uiOutput(ns("edit_1")),
h2("Selected"),
tableOutput(ns("checked"))
)
)
}
# Tab 2 server code.
tab2Server <- function(input, output, session) {
ns <- session$ns
# Helper function for making checkboxes.
shinyInput = function(FUN, len, id, ...) {
inputs = character(len)
for (i in seq_len(len)) {
inputs[i] = as.character(FUN(ns(paste0(id, i)), label = NULL, ...))
}
inputs
}
# Update table records with selection.
subsetData <- reactive({
sel <- mtcars[1:5,]
})
values <- reactiveValues(df = NULL)
observe({
values$df <- subsetData()
})
# Datatable with checkboxes.
output$mytable2 <- DT::renderDataTable(
datatable(
data.frame(values$df,Favorite=shinyInput(checkboxInput,nrow(values$df), "cbox_", width = 10)),
editable = TRUE,
selection = 'single',
escape = FALSE,
options = list(
paging = FALSE,
preDrawCallback = JS('function() {Shiny.unbindAll(this.api().table().node()); }'),
drawCallback = JS('function() {Shiny.bindAll(this.api().table().node()); }')
)
)
)
observeEvent(input$add.row_1,{
# print(paste0("Row selected",input$mytable2_rows_selected))
if (!is.null(input$mytable2_rows_selected)) {
td <- values$df
tid_n = as.numeric(input$mytable2_rows_selected)
tid = as.numeric(input$mytable2_rows_selected) + 1
if(tid_n == nrow(td)){
td<- rbind(data.frame(td[1:tid_n, ]),
data.frame(td[tid_n, ]))
}else{
td<- rbind(data.frame(td[1:tid_n, ]),
data.frame(td[tid_n, ]),
data.frame(td[tid: nrow(td), ]))
}
td <- data.frame(td)
print(td)
values$df <- td
}
})
output$edit_1 <- renderUI({
tagList(
actionButton(inputId = ns("add.row_1"), label = "Add Row", icon = icon("plus"),class = "example-css-selector",style = "background-color:gray; border-color:gray;color:white;height:31px;"),
actionButton(inputId = ns("delete.row_1"), label = "Delete Row", icon = icon("minus"),class = "example-css-selector",style = "background-color:gray; border-color:gray;color:white;height:31px;"),br(),br()
)
})
# Helper function for reading checkbox.
shinyValue = function(id, len) {
values <- unlist(lapply(seq_len(len), function(i) {
value = input[[paste0(id, i)]]
if (is.null(value)) NA else value
}))
return(values)
}
# Output read checkboxes.
observe({
len <- nrow(values$df)
output$checked <- renderTable({
data.frame(selected=shinyValue("cbox_", len))
})
})
}
# Define UI for application.
ui <- fluidPage(
useShinyjs(),
navbarPage(
'Title',
tab2UI("tab2")
)
)
# Define server.
server <- function(input, output, session) {
# Call tab2 server code.
callModule(tab2Server, "tab2")
}
# Run the application
shinyApp(ui = ui, server = server)

Problem in downloading data using Download Handlers in ShinyApp

My original data of mtcar gets downloaded using Download Handlers in ShinyApp whereas i want the the modified data (using SelectInputs) to be downloaded through Handlers.
I have attached my codes as well, please let me know whats wrong with them. Many thanks:)
library(shiny)
library(tidyr)
library(dplyr)
library(readr)
library(DT)
data_table <- mtcars
# Define UI
ui <- fluidPage(
downloadButton('downLoadFilter',"Download the filtered data"),
selectInput(inputId = "cyl",
label = "cyl:",
choices = c("All",
unique(as.character(data_table$cyl))),
selected = "4",
multiple = TRUE),
selectInput(inputId = "vs",
label = "vs:",
choices = c("All",
unique(as.character(data_table$vs))),
selected = "1",
multiple = TRUE),
DT::dataTableOutput('ex1'))
server <- function(input, output) {
thedata <- reactive({
if(input$cyl != 'All'){
return(data_table[data_table$cyl == input$cyl,])
}
else if(input$vs != 'All'){
return(data_table[data_table$vs == input$vs,])
}
else{
return(data_table)
}
})
output$ex1 <- DT::renderDataTable(DT::datatable(filter = 'top',
escape = FALSE,
options = list(pageLength =
10, scrollX='500px',autoWidth = TRUE),{
thedata() # Call reactive
thedata()
}))
output$downLoadFilter <- downloadHandler(
filename = function() {
paste('Filtered data-', Sys.Date(), '.csv', sep = '')
},
content = function(path){
write_csv(thedata(),path) # Call reactive thedata()
})}
shinyApp(ui = ui, server = server)
You are updating thedata() only inside your renderDataTable. You need to make it a reactive and then use it for being rendered as DataTable and being downloaded.
Change your server to:
# Define server logic
server <- function(input, output) {
thedata <- reactive({
if(input$cyl != 'All'){
return(data_table[data_table$cyl == input$cyl,])
}
else{
return(data_table)
}
})
output$ex1 <- DT::renderDataTable(DT::datatable(filter = 'top',
escape = FALSE,
options = list(pageLength = 10, scrollX='500px',autoWidth = TRUE),{
thedata() # Call reactive thedata()
}))
output$downLoadFilter <- downloadHandler(
filename = function() {
paste('Filtered data-', Sys.Date(), '.csv', sep = '')
},
content = function(path){
write_csv(thedata(),path) # Call reactive thedata()
})}

How to loop through multiple upload widegets in shiny?

I want to create multiple fileInput function to allow users to upload files. The main reason I am creating multiple upload widgets is because I want to allow users to upload through different path. What I am trying to accomplish here is to loop through all the fileInputs and save all the files into one dataframe but not able to do it in example of my code.
library(shiny)
library(data.table)
library(DT)
n_attachments <- sprintf("file%s",seq(1:2))
ui <- fluidPage(
titlePanel('File download'),
sidebarLayout(
sidebarPanel(
textInput("LOAN_NUMBER", label = "Fannie Mae Loan Number", placeholder = "Please enter loan #")
, textInput("REO_ID", label = "REO Number", placeholder = "Please enter REO #")
, fileInput("file1", "Attachments1", accept = c("text/csv", "text/comma-separated-values,text/plain",".csv", ".pdf", ".doc", ".xlsx"), multiple = TRUE)
, fileInput("file2", "Attachments2", accept = c("text/csv", "text/comma-separated-values,text/plain",".csv", ".pdf", ".doc", ".xlsx"), multiple = TRUE)
, textOutput('text')
),
mainPanel(
DT::dataTableOutput("table"), tags$hr()
)
)
)
server <- function(input, output) {
bin_data <- reactive({
attachement_data <- data.frame(ATTACHMENT = character(), FILENAME = character(), LOAN_NUMBER = character(), REO_ID = character())
for(x in n_attachments)
{
output$text <- renderText({ input$x })
req(input$x)
# binary_data <- paste(readBin(input$file1$datapath, what="raw", n=1e6), collapse="-")
# attachment_info <- data.frame(ATTACHMENT = binary_data, FILENAME = paste0(input$file1$name))
# attachment_info
binary_data=list()
filenames=list()
for(i in 1:length(input$x[,1])){
binary_data[[i]] <- paste(readBin(input$x[[i, 'datapath']], what = "raw", n=1e6), collapse = "-")
filenames[[i]] <- input$x[[i, 'name']]
}
bin_data_frame <- data.frame(ATTACHMENT = as.character(unlist(binary_data)), FILENAME = as.character(unlist(filenames)))
bin_data_frame$LOAN_NUMBER <- input$LOAN_NUMBER
bin_data_frame$REO_ID <- input$REO_ID
attachement_data <- rbind(attachement_data, bin_data_frame)
}
save(attachement_data, file="attachement_data.RData")
attachement_data
})
output$table <- DT::renderDataTable({
bin_data()
})
}
shinyApp(ui = ui, server = server)
ok I think I figured it out, I have to use input[[x]] instead of input$x, and I added couple lines to check how many fileinputs are uploaded.
server <- function(input, output) {
bin_data <- reactive({
attachement_data <- data.frame(ATTACHMENT = character(), FILENAME = character(), LOAN_NUMBER = character(), REO_ID = character())
k <- 0
for(x in n_attachments)
{
if(!is.null(input[[x]]))
{
k = k + 1
}
}
for(x in n_attachments[0:k])
{
if(!is.null(input[[x]]))
{
output$text <- renderText({ input[[x]] })
req(input[[x]])
# binary_data <- paste(readBin(input$file1$datapath, what="raw", n=1e6), collapse="-")
# attachment_info <- data.frame(ATTACHMENT = binary_data, FILENAME = paste0(input$file1$name))
# attachment_info
binary_data=list()
filenames=list()
for(i in 1:length(input[[x]][,1])){
binary_data[[i]] <- paste(readBin(input[[x]][[i, 'datapath']], what = "raw", n=1e6), collapse = "-")
filenames[[i]] <- input[[x]][[i, 'name']]
}
bin_data_frame <- data.frame(ATTACHMENT = as.character(unlist(binary_data)), FILENAME = as.character(unlist(filenames)))
bin_data_frame$LOAN_NUMBER <- input$LOAN_NUMBER
bin_data_frame$REO_ID <- input$REO_ID
attachement_data <- rbind(attachement_data, bin_data_frame)
}
}
save(attachement_data, file="attachement_data.RData")
attachement_data
})
output$table <- DT::renderDataTable({
bin_data()
})
}
shinyApp(ui = ui, server = server)

How to use built-in data instead of uploaded data

I have an app like below. I want to either read-in data from file upload or use the built-in data. I thought I could put an action button and if somebody hit it the input data will mount on and it goes to the next levels. My problem is later in my real app, some widgets such as selectInput have to be updated and I want to be empty until user decided whether to use uploaded data or the built-in one.
library(shiny)
x <- mtcars
ui <- fluidPage(
fileInput(inputId = "uploadcsv", "", accept = '.csv'),
actionButton(inputId = "a", label = "action button"),
selectInput("select",label = h3("Select box"),choices = "",selected = 1)
)
server <- function(input, output, session) {
data <- reactive({
infile <- input$uploadcsv
if (is.null(infile))
return(NULL)
read.csv(infile$datapath, header = TRUE, sep = ",")
})
DataToUse <- NULL
observe(!is.null(input$uploadedcsv),
DataToUse <- data()
)
observeEvent(input$a,
DataToUse <- x
)
observe({
req(DataToUse)
if (max(DataToUse$cyl) %% 4 == 0){
numberofinterval <- max(DataToUse$cyl) %/% 4
} else {
numberofinterval <- (max(DataToUse$cyl) %/% 4)+1
}
NumPeriod <- seq(0, numberofinterval)
updateSelectInput(session, inputId = "select",
choices = NumPeriod,
selected = NumPeriod)
})
}
shinyApp(ui = ui, server = server)
Something like this should do:
library(shiny)
x <- mtcars
ui <- fluidPage(
fileInput(inputId = "uploadcsv", "", accept = '.csv'),
actionButton(inputId = "a", label = "action button"),
selectInput("select",label = h3("Select box"),choices = "",selected = 1)
)
server <- function(input, output, session) {
data <- reactive({
infile <- input$uploadcsv
if (is.null(infile))
return(NULL)
read.csv(infile$datapath, header = TRUE, sep = ",")
})
v <- reactiveValues()
v$DataToUse <- NULL
observeEvent(input$uploadcsv,{
if(!is.null(input$uploadcsv)){
v$DataToUse <- data()
}
})
observeEvent(input$a,v$DataToUse <- x)
observeEvent(v$DataToUse,{
req(v$DataToUse)
if (max(v$DataToUse$cyl) %% 4 == 0){
numberofinterval <- max(v$DataToUse$cyl) %/% 4
} else {
numberofinterval <- (max(v$DataToUse$cyl) %/% 4)+1
}
NumPeriod <- seq(0, numberofinterval)
updateSelectInput(session, inputId = "select",
choices = NumPeriod,
selected = NumPeriod)
})
}
shinyApp(ui = ui, server = server)

Resources