R Shiny 将来自多个动态生成的 textAreaInput 字段的用户输入存储在服务器部分的对象中
R Shiny store the user input from multiple dynamically generated textAreaInput fields in an object in the server part
shiny
的新手,现在已经为此苦苦挣扎了两天多。
我创建了一个应用程序,用户可以在其中加载 .csv
数据文件并选择一个或多个变量,这些变量的名称在应用程序中显示为复选框。选中一个复选框时,下方会出现一个同名的新复选框,当它也被单击时,旁边会出现一个 textAreaInput
,用户可以在其中添加构成目标变量的变量名称作为比例。这是该应用程序的简化版本:
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)
加载的数据是这样生成的(只是摘录,真实的栏目和案例较多):
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)
它工作正常,没有错误。这是我在每个生成的 textAreaInput
字段中输入变量名称后的样子:
但是,我想从每个动态生成的 textAreaInput
中获取用户输入并将其存储在如下列表中:
list(VAR1 = "VAR3 VAR4 VAR5", VAR2 = "VAR6 VAR7")
或
list(VAR1 = "VAR3", "VAR4", "VAR5", VAR2 = "VAR6", "VAR7")
在应用程序的服务器部分内以备将来使用。
我尝试按照线程中的解决方案,但我没有成功找到任何解决方案,感到很困惑。有人可以帮忙吗?
首先,您要确保为每个动态添加的元素分配一个唯一的名称。您刚刚在示例中对字母 "i" 进行了硬编码。你想要像
这样的东西
textAreaInput(inputId = paste0("varconst_",i), label = paste("Variables constituting scale", i),
width = "700px", height = "100px", value = NULL)
然后你可以用类似这样的东西观察那些文本框
observeEvent(lapply(paste0("varconst_", input$selectedScoresCheckBoxes), function(x) input[[x]]), {
obj <- Map(function(x) input[[paste0("varconst_",x)]], input$selectedScoresCheckBoxes)
dput(obj)
})
这里我只是使用 dput
将列表转储到控制台,这样你就可以看到它更新了,但你可以用它做任何你想做的事。
我已经按照 MrFlick 的回答修改了应用程序的代码。为了留下完整解决方案的书面记录,我将其发布在下方。我所做的一些额外修改包括打印输出列表以及每个生成的 textAreaInput
字段的变量,以便可以在应用程序本身中查看列表。我还对 obj
添加了一些进一步的修改,在生成后,以获得所需的列表。
如果有更多动态生成的输出部分,其中包含复选框和相关文本区域,则 varconst_
索引必须在不同的代码块中保持唯一(例如 varconst1_
、varconst2_
、varconst3_
、等等)。
代码如下:
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)
shiny
的新手,现在已经为此苦苦挣扎了两天多。
我创建了一个应用程序,用户可以在其中加载 .csv
数据文件并选择一个或多个变量,这些变量的名称在应用程序中显示为复选框。选中一个复选框时,下方会出现一个同名的新复选框,当它也被单击时,旁边会出现一个 textAreaInput
,用户可以在其中添加构成目标变量的变量名称作为比例。这是该应用程序的简化版本:
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)
加载的数据是这样生成的(只是摘录,真实的栏目和案例较多):
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)
它工作正常,没有错误。这是我在每个生成的 textAreaInput
字段中输入变量名称后的样子:
但是,我想从每个动态生成的 textAreaInput
中获取用户输入并将其存储在如下列表中:
list(VAR1 = "VAR3 VAR4 VAR5", VAR2 = "VAR6 VAR7")
或
list(VAR1 = "VAR3", "VAR4", "VAR5", VAR2 = "VAR6", "VAR7")
在应用程序的服务器部分内以备将来使用。
我尝试按照
首先,您要确保为每个动态添加的元素分配一个唯一的名称。您刚刚在示例中对字母 "i" 进行了硬编码。你想要像
这样的东西textAreaInput(inputId = paste0("varconst_",i), label = paste("Variables constituting scale", i),
width = "700px", height = "100px", value = NULL)
然后你可以用类似这样的东西观察那些文本框
observeEvent(lapply(paste0("varconst_", input$selectedScoresCheckBoxes), function(x) input[[x]]), {
obj <- Map(function(x) input[[paste0("varconst_",x)]], input$selectedScoresCheckBoxes)
dput(obj)
})
这里我只是使用 dput
将列表转储到控制台,这样你就可以看到它更新了,但你可以用它做任何你想做的事。
我已经按照 MrFlick 的回答修改了应用程序的代码。为了留下完整解决方案的书面记录,我将其发布在下方。我所做的一些额外修改包括打印输出列表以及每个生成的 textAreaInput
字段的变量,以便可以在应用程序本身中查看列表。我还对 obj
添加了一些进一步的修改,在生成后,以获得所需的列表。
如果有更多动态生成的输出部分,其中包含复选框和相关文本区域,则 varconst_
索引必须在不同的代码块中保持唯一(例如 varconst1_
、varconst2_
、varconst3_
、等等)。
代码如下:
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)