Dynamically adding column names in R Shiny - r

Quite New to R here and not an experienced coder. I want to create a simple function to upload an external file via R shiny, but the file will not have fixed number of columns and may or may not have a column name.
In the case where the raw file does not have a header, I wish to force the name of the first column to be "Date" and the remaining columns 2,3,4...,n to be "Investment 1","Investment 2","Investment 3",...,"Investment n-1" respectively
Here's my current code, server side,
server <- function(input, output) {
rawdata <- reactive({
file_to_read = input$file
if(is.null(file_to_read)) {
return()
}
data <- read.table(file_to_read$datapath, sep = input$sep, header =
input$dataheader)
})
addcolumn <- reactive({
if(input$dataheader = FALSE) {
paste("Date",colnames(rawdata()[,1]))
for (i in 2:ncol(rawdata())) {
paste("Investment " + i, colnames(rawdata()[,i]))
}
}
})
output$datatable <- renderTable({
If(input$dataheader = FALSE) {
addcolumn(rawdata())
} else {
rawdata()
}
})
and ui side,
dashboardBody(
tabItems(
tabItem(
tabName = "import",
fluidRow(
box(
title = "Instructions",
solidHeader = TRUE,
width = 12,
status = "warning",
height = 120,
textOutput("instructionsImport")
),
box(
solidHeader = FALSE,
width = 3,
status = "primary",
fileInput("file","Choose a file to upload"),
radioButtons("sep","Separator",choices = c(Comma = ",", Space = " ",Period = ".", Tilde = "~", minus = "-")),
checkboxInput("dataheader","File has header?")
),
box(
title = "Uploaded Data",
solidHeader = TRUE,
width = 9,
status = "primary",
tableOutput("datatable")
)
)
),
Ideally, I would like the operation of adding column name to be done once after import and the resulting data table created instead of making a reactive function for adding column.
Thanks

Just change your server.R code to that :
server <- function(input, output) {
rawdata <- reactive({
file_to_read = input$file
if(is.null(file_to_read)) {
return()
}
data <- read.table(file_to_read$datapath, sep = input$sep, header =
input$dataheader)
if(!input$dataheader){
colnames(data)<-c("Date",paste("Investment",1:(ncol(data)-1)))
}
return(data)
})
output$datatable <- renderTable({
rawdata()
})
}

Related

How to combine multiple R modules (with submodels and uiOuput) using shinydashboard?

I'm modularizing a Shiny app I developed using shinydashboard packages. Despite it traditionally works when I use it without involving modules, I can't make it work when I try to divide it into modules and submodules. Here I would like to combine two UIs (one for the sidebar, one for the body) in order to upload a dataset from the sidebar and show it into the body.
I'd be very glad if anybody could provide me some help with this.
Here is the code of the general Shiny app:
library(shiny)
library(excelR)
library(vroom)
library(readxl)
library(janitor)
library(dplyr)
library(shinydashboard)
library(shinydashboardPlus)
# # load separate module and function scripts
source("modules.R")
# app_ui
app_ui <- function() {
tagList(
shinydashboardPlus::dashboardPagePlus(
header = shinydashboardPlus::dashboardHeaderPlus(title = "module_test",
enable_rightsidebar = FALSE),
sidebar = shinydashboard::dashboardSidebar(
shinydashboard::sidebarMenu(id = "tabs",
import_sidebar_ui("import"))
),
body = shinydashboard::dashboardBody(shinydashboard::tabItems(
import_body_ui("import"))
),
rightsidebar = NULL,
title = "Module App"
)
)
}
# app_server
app_server <- function(input, output, session) {
shiny::moduleServer(id = "import", module = import_server)
}
####################################################################
run_app <- function(...) {
shiny::shinyApp(
ui = app_ui,
server = app_server)
}
#---------------------------------
run_app()
and here is the modules.R file I wrote containing the UIs for sidebar and body, plus the server:
# Import module ####
#
# Import sidebar UI
import_sidebar_ui <- function(id) {
ns <- NS(id)
shinydashboard::menuItem("Module Testing",
tabName = "tab_testing_mod",
icon = icon("th"),
tagList(
selectInput(ns("input_type"),
"Type of file:",
choices = c("Choose one" = "",".csv" = "csv",
".txt" = "txt", ".xls/.xlsx" = "xlsx"),
selected = NULL),
uiOutput(ns("inputControls")),
fileInput(ns("file"), "Data", buttonLabel = "Upload..."),
checkboxInput(ns("rownames"), "Check if 1st column contains rownames"),
checkboxInput(ns("constant"), "Remove constant columns?"),
checkboxInput(ns("empty"), "Remove empty cols?"),
actionButton(ns("bttn_import"), "Import data")
)
)
}
# Import body UI
import_body_ui <- function(id) {
ns <- NS(id)
shinydashboard::tabItem(tabName = "tab_testing_mod",
fluidRow(
h3("Imported Data"),
excelR::excelOutput(ns("preview")))
)
}
# Import server
import_server <- function(input, output, session) {
ns <- session$ns
output$inputControls <- renderUI({
tagList(
switch(input$input_type,
"csv" = textInput("delim", "Delimiter (leave blank to guess)", ""),
"txt" = textInput("delim", "Delimiter (leave blank to guess)", "")
),
switch(input$input_type,
"xlsx" = numericInput("sheet", "Sheet number", value = 1))
)
})
raw <- reactive({
req(input$file)
if (input$input_type == "csv" || input$input_type == "txt") {
delim <- if (input$delim == "") NULL else input$delim
data <- vroom::vroom(input$file$datapath, delim = delim)
} else if (input$input_type == "xlsx") {
data <- tibble::as.tibble(readxl::read_excel(input$file$datapath, sheet = input$sheet, col_names = TRUE))
} else {
return(NULL)
}
raw <- data
raw
})
tidied <- eventReactive(input$bttn_import,{
out <- raw()
if (input$empty) {
out <- janitor::remove_empty(out, "cols")
}
if (input$constant) {
out <- janitor::remove_constant(out)
}
if (input$rownames) {
out <- tibble::column_to_rownames(out, var = colnames(out[1]))
}
out <- out %>% dplyr::mutate_if(is.character,as.factor)
out
})
output$preview <- excelR::renderExcel({
excelR::excelTable(data = raw(),
colHeaders = toupper(colnames(raw())),
fullscreen = FALSE,
columnDrag = TRUE,
rowDrag = TRUE,
wordWrap = FALSE,
search =TRUE,
showToolbar = TRUE,
minDimensions = c(ncol(raw()),10)
)
})
}
It seems to me I can upload the dataset (.csv, .txt or .xlsx) files but I can't show it into the body.
I'd be very glad if you can help me, thank you very much in advance for your assistance.

How to use Shiny inputs to Filter Datatable that has been edited?

I'm stumped on a three part process:
I'm trying to filter what is displayed to a dataTable via Shiny inputs (in the real app there would be dozens of these).
Then, I'd like to edit cell values in the DT.
Finally, I'd like to be able to change the filters and keep the edited cell values.
The example app below does 1 and 2, but not 3. After I make an edit AND click the only_johns checkbox, the dataTable displays the original data.
Any ideas would be appreciated!
library(shiny)
library(shinydashboard)
library(tidyverse)
library(DT)
header <- dashboardHeader(title = "demo")
sidebar <- dashboardSidebar(
sidebarMenu(
downloadButton("downloadResults","Download Results"),
checkboxInput("only_johns", "only_johns")
)
)
body <- dashboardBody(
tabItems(
tabItem(
tabName = 'admin', class = 'active',
fluidRow(
box(
dataTableOutput('userTable'), width = 6
)
)
)
)
)
ui <- dashboardPage(title = 'admin function test', header, sidebar, body)
server <- function(input, output, session){
#1
start.df <- reactiveValues(data=NA)
start.df$data <- data.frame(userName = rep(c("John","Ida","Mike"),20),
id = 1:60, stringsAsFactors = FALSE)
#2 temp display filters df
display.df <- reactiveValues(data=start.df)
observe({
temp <- isolate(start.df$data)
if (input$only_johns) {
display.df$data <- temp[temp$userName == "John",]
} else {
display.df$data <- temp
}
})
# Display editable datatable
output$userTable <- renderDataTable({
req(display.df$data)
DT::datatable(isolate(display.df$data),
editable = TRUE,
rownames = FALSE)
})
###Tracking Changes###
proxy = dataTableProxy('userTable')
observe({
DT::replaceData(proxy, display.df$data, rownames = FALSE, resetPaging = FALSE)
})
observeEvent(input$userTable_cell_edit, {
display.df$data <<- editData(display.df$data, input$userTable_cell_edit, rownames = FALSE)
})
output$downloadResults <- downloadHandler(
filename = function(){paste("userTest.csv", sep = "")},
content = function(file){write.csv(start.df$data, file, row.names = FALSE)}
)
}
shinyApp(ui = ui, server = server)
So far you only update the diplay.df$data, but you need to update the original start.df$data. I've included this in my solution, to find the correct row irrespective of the current filtering, I've introduced the column row_id that is hidden in the DT. Also, I've simplified your code a bit.
library(shiny)
library(shinydashboard)
library(tidyverse)
library(DT)
header <- dashboardHeader(title = "demo")
sidebar <- dashboardSidebar(
sidebarMenu(
downloadButton("downloadResults","Download Results"),
checkboxInput("only_johns", "only_johns")
)
)
body <- dashboardBody(
tabItems(
tabItem(
tabName = 'admin', class = 'active',
fluidRow(
box(
dataTableOutput('userTable'), width = 6
)
)
)
)
)
ui <- dashboardPage(title = 'admin function test', header, sidebar, body)
server <- function(input, output, session){
#1
start.df <- reactiveValues(data=NA)
start.df$data <- data.frame(userName = rep(c("John","Ida","Mike"),20),
id = 1:60,
row_id = 1:60,
stringsAsFactors = FALSE)
#2 temp display filters df
display.df <- reactiveValues(data=start.df)
observeEvent(input$only_johns, {
temp <- isolate(start.df$data)
if (input$only_johns) {
display.df$data <- temp[temp$userName == "John",]
} else {
display.df$data <- temp
}
})
# Display editable datatable
output$userTable <- renderDataTable({
req(display.df$data)
DT::datatable(isolate(display.df$data),
editable = TRUE,
rownames = FALSE,
options = list(
columnDefs = list(
list(
visible = FALSE,
targets = 2
)
)
))
})
###Tracking Changes###
proxy = dataTableProxy('userTable')
observeEvent(input$userTable_cell_edit, {
display.df$data <- editData(display.df$data, input$userTable_cell_edit, rownames = FALSE)
DT::replaceData(proxy, display.df$data, rownames = FALSE, resetPaging = FALSE)
# update the data in the original df
# get the correct row_id
curr_row_id <- display.df$data[input$userTable_cell_edit[["row"]], "row_id", drop = TRUE]
# get the correct column position
column_pos <- input$userTable_cell_edit[["col"]] + 1 # DT starts indexing at 0
# update the data
temp <- start.df$data
temp[temp$row_id == curr_row_id, column_pos] <- input$userTable_cell_edit[["value"]]
start.df$data <- temp
})
output$downloadResults <- downloadHandler(
filename = function(){paste("userTest.csv", sep = "")},
content = function(file){write.csv(start.df$data, file, row.names = FALSE)}
)
}
shinyApp(ui, server)
Edit
Here is a version where the page gets not reset. The problem was that with the edited data, display.df$data was changed, which triggered the rerendering of output$userTable and this resetted the page. To circumvent this, I've added another reactive value that contains the edited data and don't change display.df anymore, it is only changed by changing the input filtering.
library(shiny)
library(shinydashboard)
library(tidyverse)
library(DT)
header <- dashboardHeader(title = "demo")
sidebar <- dashboardSidebar(
sidebarMenu(
downloadButton("downloadResults","Download Results"),
checkboxInput("only_johns", "only_johns")
)
)
body <- dashboardBody(
tabItems(
tabItem(
tabName = 'admin', class = 'active',
fluidRow(
box(
dataTableOutput('userTable'), width = 6
)
)
)
)
)
ui <- dashboardPage(title = 'admin function test', header, sidebar, body)
server <- function(input, output, session){
#1
start.df <- reactiveValues(data=NA)
start.df$data <- data.frame(userName = rep(c("John","Ida","Mike"),20),
id = 1:60,
row_id = 1:60,
stringsAsFactors = FALSE)
#2 temp display filters df
display.df <- reactiveValues(data=isolate(start.df))
edit.df <- reactiveValues(data = isolate(start.df))
observeEvent(input$only_johns, {
temp <- isolate(start.df$data)
if (input$only_johns) {
display.df$data <- temp[temp$userName == "John",]
edit.df$data <- temp[temp$userName == "John",]
} else {
display.df$data <- temp
edit.df$data <- temp
}
})
# Display editable datatable
output$userTable <- renderDataTable({
req(display.df$data)
DT::datatable(display.df$data,
editable = TRUE,
rownames = FALSE,
options = list(
columnDefs = list(
list(
visible = FALSE,
targets = 2
)
)
))
})
###Tracking Changes###
proxy = dataTableProxy('userTable')
observeEvent(input$userTable_cell_edit, {
edit.df$data <- editData(edit.df$data, input$userTable_cell_edit, rownames = FALSE)
DT::replaceData(proxy, edit.df$data, rownames = FALSE, resetPaging = FALSE)
# update the data in the original df
# get the correct row_id
curr_row_id <- edit.df$data[input$userTable_cell_edit[["row"]], "row_id", drop = TRUE]
# get the correct column position
column_pos <- input$userTable_cell_edit[["col"]] + 1 # DT starts indexing at 0
# update the data
temp <- start.df$data
temp[temp$row_id == curr_row_id, column_pos] <- input$userTable_cell_edit[["value"]]
start.df$data <- temp
})
output$downloadResults <- downloadHandler(
filename = function(){paste("userTest.csv", sep = "")},
content = function(file){write.csv(start.df$data, file, row.names = FALSE)}
)
}
shinyApp(ui, server)
__
Hello!
This post is very interesting.
I have used the same code above, but when I edit a cell, an error message occurs for users : "Warning : JSON invalid response" at each edition !
Everything seems correct. How can I delete this error message ?
I try this but it does not work :
tags$script(HTML("$.fn.dataTable.ext.errMode = 'throw';")),
Many thanks for your collaboration,
Kind regards,

Content of the table disappears after filtration

I need to pass filtration from configuration file to datatable. When the table is rendered the user must be able to clean the filtration and see the full content of the table
The problem arises when the filtration is applied to factor columns. In this case the content of the table is rendered but is not shown in the table. It is necessary click additionally on the filter and choose another value. But it still works fine with character columns. How one may fix it?
There is an example which reproduce my problem.
library(shiny)
library(DT)
ui <- fluidPage(
fluidRow(
selectInput(inputId = "table_fltration",
label = 'Choose table filtration',
choices = c("Working example",
"Not working example"),
selected = "Working example"),
actionButton(inputId = 'update_btn', label = "Use config")),
fluidRow(dataTableOutput("iris_table"))
)
server <- function(input, output, session) {
columns_search <- reactive({
if (input$table_fltration == "Working example") {
ex <- c("7.2 ... 7.9", "", "", "", "", "[\"anything\"]")
} else {
ex <- c("", "", "", "", "[\"anything\"]", "")
}
columns_search <- list()
for ( i in 1:length(ex)) {
if(ex[i] != "") {
element = list(list(search = ex[i]))
} else {element = NULL}
columns_search[i] <- element
}
columns_search
})
iris_table_ex <- reactive({
iris$Species_2 = as.character(iris$Species)
iris
})
observeEvent(input$update_btn,
output$iris_table <- DT::renderDataTable({
DT::datatable(iris_table_ex(),
filter = list(position = 'top'),
class = 'hover',
rownames = FALSE,
options = list(orderClasses = TRUE,
stateSave = FALSE,
searchHighlight = TRUE,
searchCols = columns_search(),
scrollX = TRUE,
paging = TRUE,
pageLength = 10))
})
)
}
shinyApp(ui, server)

Use values from edited table for calculations in Shiny

What I am attempting to do, is to allow the user to pass in a configuration/lookup excel table into shiny, display this table in shiny, allow the user to make cells edits in shiny, and use the values that were edited from the editable table for calculations. My problem arises for the last step "use the values that were edited from the editable table for calculations".
The excel file consists of 2 tabs with data of the following content:
Tab1 Name: "parameters"
data.frame(Name = c("a", "b", "c"), Value = c(1:3))
Tab2 Name: "parameters2"
data.frame(Name = c("a", "b", "c"), Value = c(4:6))
The ideal shiny app would do the following:
1) At upload, perform a calculation adding the unchanged first values of Tab 1 and Tab 2. This would be 1 + 4 = 5.
2) If user edits Tab 1's value of 1 to 8, then the calculation would result in 8 + 4 = 12.
Effectively, I want to use the edited tables values to update all my calculations if the user makes any edits to it. I know this can be done by simply uploading a new file in shiny, but I would rather allow them to do this in shiny as opposed to uploading a new file.
Here is my shiny app. Appreciate any help/guidance!
library(shiny)
library(DT)
shinyApp(
ui <- fluidPage(
fileInput(inputId = "config", label = "Upload Configuration File",
multiple = F, accept = c(".xlsx", ".xls")),
verbatimTextOutput("txt"),
tagList(tags$head(tags$style(type = 'text/css','.navbar-brand{display:none;}')),
navbarPage(title = "",
tabPanel(title = "Parameters",
dataTableOutput(outputId = "edit.param", width = 2)),
tabPanel(title = "Parameters2",
dataTableOutput(outputId = "edit.param2", width = 2))
)
)
),
server = function(input, output, session) {
config.path = reactive({
inFile = input$config
if(is.null(inFile)) {
return(NULL)
} else {
return(inFile$datapath)
}
})
df.param = reactive({
read_excel(path = config.path(), sheet = "parameters")
})
df.param2 = reactive({
read_excel(path = config.path(), sheet = "parameters2")
})
output$edit.param = renderDT(df.param(), selection = "none", server = F, editable = "cell")
output$edit.param2 = renderDT(df.param2(), selection = "none", server = F, editable = "cell")
observeEvent(input$edit.param_cell_edit, {
df.param()[input$edit.param_cell_edit$row, input$edit.param_cell_edit$col] <<- input$edit.param_cell_edit$value
})
observeEvent(input$edit.param2_cell_edit, {
df.param()[input$edit.param2_cell_edit$row, input$edit.param2_cell_edit$col] <<- input$edit.param2_cell_edit$value
})
output$txt = reactive({
df.param()$value[1] + df.param2()$value[1]
})
}
)
I also tried this for the server section and had no luck either:
output$edit.param = renderDT(df.param(), selection = "none", server = F, editable = "cell")
output$edit.param2 = renderDT(df.param2(), selection = "none", server = F, editable = "cell")
observe(input$edit.param_cell_edit)
observe(input$edit.param2_cell_edit)
Could you try this? (I have not tried).
library(shiny)
library(DT)
shinyApp(
ui <- fluidPage(
fileInput(inputId = "config", label = "Upload Configuration File",
multiple = F, accept = c(".xlsx", ".xls")),
verbatimTextOutput("txt"),
tagList(tags$head(tags$style(type = 'text/css','.navbar-brand{display:none;}')),
navbarPage(title = "",
tabPanel(title = "Parameters",
dataTableOutput(outputId = "edit_param", width = 2)),
tabPanel(title = "Parameters2",
dataTableOutput(outputId = "edit_param2", width = 2))
)
)
),
server = function(input, output, session) {
config.path = reactive({
inFile = input$config
if(is.null(inFile)) {
return(NULL)
} else {
return(inFile$datapath)
}
})
df_param <- reactiveVal()
observe({
req(config.path())
df_param(read_excel(path = config.path(), sheet = "parameters"))
})
df_param2 <- reactiveVal()
observe({
req(config.path())
df_param2(read_excel(path = config.path(), sheet = "parameters2"))
})
output$edit_param = renderDT({
req(df_param())
datatable(isolate(df_param()), selection = "none", editable = "cell")
})
output$edit_param2 = renderDT({
req(df_param2())
datatable(isolate(df_param2()), selection = "none", editable = "cell")
})
proxy <- dataTableProxy("edit_param")
proxy2 <- dataTableProxy("edit_param2")
observeEvent(input$edit_param_cell_edit, {
info <- input$edit_param_cell_edit
df_param(editData(df_param(), info, proxy, resetPaging = FALSE))
})
observeEvent(input$edit_param2_cell_edit, {
info <- input$edit_param2_cell_edit
df_param2(editData(df_param2(), info, proxy2, resetPaging = FALSE))
})
output$txt = renderPrint({
df_param()$value[1] + df_param2()$value[1]
})
}
)

R Shiny store the user input from multiple dynamically generated textAreaInput fields in an object in the server part

New to shiny and struggling with this for more than two days now.
I have created an application where the user loads .csv data file and chooses one or more variables whose names appear in the application as check boxes. When a checkbox is checked, a new checkbox appears under with the same name and when it is clicked too, a textAreaInput appears next to it where the user can add variable names that constitute the target variable as a scale. Here is an oversimplified version of the application:
library(shiny)
ui <- fluidPage(
mainPanel(
fileInput(inputId = "file", label = "Choose File", multiple = TRUE, accept = ".csv"),
uiOutput(outputId = "varCheckBoxesIndivScores"),
column(width = 3,
uiOutput(outputId = "selectedScoresCheckBoxes")),
conditionalPanel(condition = "input.selectedScoresCheckBoxes",
column(width = 6,
uiOutput(outputId = "variablesConstitutingScale"))
)
)
)
server = function(input, output, session) {
df <- reactive({
if(is.null(input$file)) {
return(NULL)
} else {
tbl <- fread(input$file$datapath, stringsAsFactors = TRUE)
return(tbl)
}
})
output$varCheckBoxesIndivScores <- renderUI({
if(is.null(df())) {
return(NULL)
} else if(!is.null(df())) {
return(tags$div(align = "left",
class = "multicol",
checkboxGroupInput(inputId = "varCheckBoxesIndivScores",
label = "Select variables",
choices = colnames(df()))))
}
})
output$selectedScoresCheckBoxes <- renderUI({
if(is.null(df())) {
return(NULL)
} else if(!is.null(df())) {
return(tags$div(align = "left",
checkboxGroupInput(inputId = "selectedScoresCheckBoxes",
label = "",
choices = input$varCheckBoxesIndivScores)))
}
})
output$variablesConstitutingScale <- renderUI({
if(is.null(df())) {
return(NULL)
} else if(!is.null(df()) & length(input$selectedScoresCheckBoxes > 0)) {
var.list.input.fields <- lapply(input$selectedScoresCheckBoxes, function(i) {
textAreaInput(inputId = "i", label = paste("Variables constituting scale", i), width = "700px", height = "100px", value = NULL)
})
var.list.input.fields
}
})
}
shinyApp(ui = ui, server = server)
The data to load is generated like this (just an excerpt, the real one has more columns and cases):
library(data.table)
x <- data.table(ID = c(2201:2220), VAR1 = rnorm(n = 20, mean = 10, sd = 2),
VAR2 = rnorm(n = 20, mean = 100, sd = 20), VAR3 = 1:20, VAR4 = 21:40,
VAR5 = 41:60, VAR6 = 61:80, VAR7 = 81:100)
write.csv(x = x, file = "/tmp/test_data.csv", row.names = FALSE)
It works fine, no errors. Here is how it looks, after I enter the variable names in each of the generated textAreaInput fields:
However, I would like to take the user input from each dynamically generated textAreaInput and store it in a list like:
list(VAR1 = "VAR3 VAR4 VAR5", VAR2 = "VAR6 VAR7")
or
list(VAR1 = "VAR3", "VAR4", "VAR5", VAR2 = "VAR6", "VAR7")
inside the server part of the application for future use.
I tried to follow the solution in this thread, but I did not succeed to come to any solution and feel quite confused. Can someone help?
First, you want to make sure to assign each of your dynimcally added elements to have a unique name. You have just hard coded the letter "i" in the sample. You want something like
textAreaInput(inputId = paste0("varconst_",i), label = paste("Variables constituting scale", i),
width = "700px", height = "100px", value = NULL)
Then you can observe those text boxes with something like this
observeEvent(lapply(paste0("varconst_", input$selectedScoresCheckBoxes), function(x) input[[x]]), {
obj <- Map(function(x) input[[paste0("varconst_",x)]], input$selectedScoresCheckBoxes)
dput(obj)
})
Here I just used dput to dump the list to the console so you can see it as it gets updated but you can do whatever you want with that.
I have modified the code of the application as per MrFlick's answer. To leave a paper trail of the complete solution, I am posting it below. The few additional modifications I have made include the printout of the list with the variables for each of the generated textAreaInput fields, so that the list can be viewed in the application itself. I have also added some further modifications of the obj, after it is generated, to obtain the list as desired.
If there are more dynamically generated output sections where check boxes and related text areas, the varconst_ index has to be made unique across the different chunks of code (e.g. varconst1_, varconst2_, varconst3_, etc.).
Here is the code:
library(shiny)
ui <- fluidPage(
mainPanel(
fileInput(inputId = "file", label = "Choose File", multiple = TRUE, accept = ".csv"),
uiOutput(outputId = "varCheckBoxesIndivScores"),
fluidRow(
column(width = 3,
uiOutput(outputId = "selectedScoresCheckBoxes")),
conditionalPanel(condition = "input.selectedScoresCheckBoxes",
column(width = 6,
uiOutput(outputId = "variablesConstitutingScale")))),
br(),
fluidRow(
conditionalPanel(condition = "input.selectedScoresCheckBoxes",
verbatimTextOutput(outputId = "scalesVarList")))
)
)
server = function(input, output, session) {
df <- reactive({
if(is.null(input$file)) {
return(NULL)
} else {
tbl <- fread(input$file$datapath, stringsAsFactors = TRUE)
return(tbl)
}
})
output$varCheckBoxesIndivScores <- renderUI({
if(is.null(df())) {
return(NULL)
} else if(!is.null(df())) {
return(tags$div(align = "left",
class = "multicol",
checkboxGroupInput(inputId = "varCheckBoxesIndivScores",
label = "Select variables",
choices = colnames(df()))))
}
})
output$selectedScoresCheckBoxes <- renderUI({
if(is.null(df())) {
return(NULL)
} else if(!is.null(df())) {
return(tags$div(align = "left",
checkboxGroupInput(inputId = "selectedScoresCheckBoxes",
label = "",
choices = input$varCheckBoxesIndivScores)))
}
})
output$variablesConstitutingScale <- renderUI({
if(is.null(df())) {
return(NULL)
} else if(!is.null(df()) & length(input$selectedScoresCheckBoxes > 0)) {
var.list.input.fields <- lapply(input$selectedScoresCheckBoxes, function(i) {
textAreaInput(inputId = paste0("varconst_",i), label = paste("Variables constituting scale", i),
width = "700px", height = "100px", value = NULL)
})
var.list.input.fields
}
})
observeEvent(lapply(paste0("varconst_", input$selectedScoresCheckBoxes), function(x) input[[x]]), {
obj <- Map(function(x) input[[paste0("varconst_",x)]], input$selectedScoresCheckBoxes)
obj <- sapply(obj, function(i) {
if(length(i) > 0) {
strsplit(x = i, split = " ")
}
})
dput(obj)
output$scalesVarList <- renderPrint({
if(is.null(df())) {
return(NULL)
} else if(!is.null(df()) && length(input$selectedScoresCheckBoxes) > 0 && length(obj) > 0) {
print(obj)
}
})
})
}
shinyApp(ui = ui, server = server)

Resources