添加或删除输入后保留 UI 个文本输入
Keep UI Text Input after adding or removing Inputs
我正在构建一个小型 UI,用户将在其中输入一个 splitLayout 文本行,该文本行构建一个语句(此问题不需要)来解决难题。
但是,如果用户决定 he/she 需要 额外的 行 或更少的 行来解决这个难题,我会比如添加或删除新的输入行而不是删除剩余的输入行。
* 灰色是占位符。
我怎样才能最好地达到我想要的结果:
请在下面找到我修剪过的代码。感谢您的输入。
library(shiny)
# Define UI
ui <- fluidPage(
# Application title
titlePanel("Identify A, B and C"),
sidebarLayout(
sidebarPanel(width = 5,
helpText("Present a statement and receive a response: 1 is a Knight who always tells the truth, 2 is a Knave who always lies, and 3 is a Normal who can do either."),
# Number of Questions
numericInput(inputId = "Questions", label = "Number of Questions",
value = 1, min = 1, max = 10, step = 1),
splitLayout(cellWidths = c("25%","70%"),
style = "border: 1px solid silver;",
cellArgs = list(style = "padding: 3px"),
uiOutput("textQuestions"), uiOutput("textQuestions2"))
),
mainPanel(
# Right hand side output
)
)
)
# Define server logic
server <- function(input, output) {
####### I don't want these to delete initially everytime??
output$textQuestions <- renderUI({
Questions <- as.integer(input$Questions)
lapply(1:Questions, function(i) {
textInput(inputId = paste0("Who", i), label = paste0(i, ". Ask:"), placeholder = "A")
})
})
########
output$textQuestions2 <- renderUI({
Questions <- as.integer(input$Questions)
lapply(1:Questions, function(i) {
textInput(inputId = paste0("Q", i) , label = paste0("Logic:"),
value = "", placeholder = "A == 1 & (B != 2 | C == 3)")
})
})
######
}
# Run the application
shinyApp(ui = ui, server = server)
您可以将其存储在反应值中:
global <- reactiveValues(ask = c(), logic = c())
observe({
Questions <- as.integer(input$Questions)
lapply(1:Questions, function(i) {
inputVal <- input[[paste0("Who", i)]]
if(!is.null(inputVal)){
global$logic[i] <- inputVal
}
inputValQ <- input[[paste0("Q", i)]]
if(!is.null(inputValQ)){
global$ask[i] <- inputValQ
}
})
})
这将为您生成以下代码示例:
作为副作用,如果输入被删除然后重新获取,这些值也会被存储。
library(shiny)
# Define UI
ui <- fluidPage(
# Application title
titlePanel("Identify A, B and C"),
sidebarLayout(
sidebarPanel(width = 5,
helpText("Present a statement and receive a response: 1 is a Knight who always tells the truth, 2 is a Knave who always lies, and 3 is a Normal who can do either."),
# Number of Questions
numericInput(inputId = "Questions", label = "Number of Questions",
value = 1, min = 1, max = 10, step = 1),
splitLayout(cellWidths = c("25%","70%"),
style = "border: 1px solid silver;",
cellArgs = list(style = "padding: 3px"),
uiOutput("textQuestions"), uiOutput("textQuestions2"))
),
mainPanel(
# Right hand side output
)
)
)
# Define server logic
server <- function(input, output) {
global <- reactiveValues(ask = c(), logic = c())
observe({
Questions <- as.integer(input$Questions)
lapply(1:Questions, function(i) {
inputVal <- input[[paste0("Who", i)]]
if(!is.null(inputVal)){
global$ask[i] <- inputVal
}
inputValQ <- input[[paste0("Q", i)]]
if(!is.null(inputValQ)){
global$logic[i] <- inputValQ
}
})
})
####### I don't want these to delete initially everytime??
output$textQuestions <- renderUI({
Questions <- as.integer(input$Questions)
lapply(1:Questions, function(i) {
textInput(inputId = paste0("Who", i), label = paste0(i, ". Ask:"), placeholder = "A", value = global$ask[i])
})
})
########
output$textQuestions2 <- renderUI({
Questions <- as.integer(input$Questions)
lapply(1:Questions, function(i) {
textInput(inputId = paste0("Q", i) , label = paste0("Logic:"), value = global$logic[i],
placeholder = "A == 1 & (B != 2 | C == 3)")
})
})
######
}
# Run the application
shinyApp(ui = ui, server = server)
看起来有人已经用 uiOutput
+renderUI
给了你答案,所以我要走另一条路:使用 insertUI
和 removeUI
.
我没有用 "number of questions" 的数字输入,而是用 "add question" 的按钮和 "remove question" 的按钮代替。我有一个变量来跟踪有多少问题。每按一次 "add question",我们就添加一行。当按下 "remove question" 时,我们删除最后一行。
代码如下:
library(shiny)
# Define UI
ui <- fluidPage(
# Application title
titlePanel("Identify A, B and C"),
sidebarLayout(
sidebarPanel(
width = 5,
helpText("Present a statement and receive a response: 1 is a Knight who always tells the truth, 2 is a Knave who always lies, and 3 is a Normal who can do either."),
# Buttons to add/remove a question
actionButton("add", "Add question"),
actionButton("remove", "Remove question"),
div(id = "questions",
style = "border: 1px solid silver;")
),
mainPanel(
# Right hand side output
)
)
)
# Define server logic
server <- function(input, output) {
# Keep track of the number of questions
values <- reactiveValues(num_questions = 0)
# Add a question
observeEvent(input$add, ignoreNULL = FALSE, {
values$num_questions <- values$num_questions + 1
num <- values$num_questions
insertUI(
selector = "#questions", where = "beforeEnd",
splitLayout(
cellWidths = c("25%","70%"),
cellArgs = list(style = "padding: 3px"),
id = paste0("question", num),
textInput(inputId = paste0("Who", num),
label = paste0(num, ". Ask:"),
placeholder = "A"),
textInput(inputId = paste0("Q", num) ,
label = paste0("Logic:"),
placeholder = "A == 1 & (B != 2 | C == 3)")
)
)
})
# Remove a question
observeEvent(input$remove, {
num <- values$num_questions
# Don't let the user remove the very first question
if (num == 1) {
return()
}
removeUI(selector = paste0("#question", num))
values$num_questions <- values$num_questions - 1
})
}
# Run the application
shinyApp(ui = ui, server = server)
编辑
OP 请求一种根据问题编号检索用户输入的方法。为此:
将以下内容添加到UI
numericInput("question_num", "Show question number", 1),
textOutput("question")
将以下内容添加到服务器
get_question <- function(q) {
paste(
input[[paste0("Who", q)]],
":",
input[[paste0("Q", q)]]
)
}
output$question <- renderText({
get_question(input$question_num)
})
我正在构建一个小型 UI,用户将在其中输入一个 splitLayout 文本行,该文本行构建一个语句(此问题不需要)来解决难题。
但是,如果用户决定 he/she 需要 额外的 行 或更少的 行来解决这个难题,我会比如添加或删除新的输入行而不是删除剩余的输入行。
我怎样才能最好地达到我想要的结果:
请在下面找到我修剪过的代码。感谢您的输入。
library(shiny)
# Define UI
ui <- fluidPage(
# Application title
titlePanel("Identify A, B and C"),
sidebarLayout(
sidebarPanel(width = 5,
helpText("Present a statement and receive a response: 1 is a Knight who always tells the truth, 2 is a Knave who always lies, and 3 is a Normal who can do either."),
# Number of Questions
numericInput(inputId = "Questions", label = "Number of Questions",
value = 1, min = 1, max = 10, step = 1),
splitLayout(cellWidths = c("25%","70%"),
style = "border: 1px solid silver;",
cellArgs = list(style = "padding: 3px"),
uiOutput("textQuestions"), uiOutput("textQuestions2"))
),
mainPanel(
# Right hand side output
)
)
)
# Define server logic
server <- function(input, output) {
####### I don't want these to delete initially everytime??
output$textQuestions <- renderUI({
Questions <- as.integer(input$Questions)
lapply(1:Questions, function(i) {
textInput(inputId = paste0("Who", i), label = paste0(i, ". Ask:"), placeholder = "A")
})
})
########
output$textQuestions2 <- renderUI({
Questions <- as.integer(input$Questions)
lapply(1:Questions, function(i) {
textInput(inputId = paste0("Q", i) , label = paste0("Logic:"),
value = "", placeholder = "A == 1 & (B != 2 | C == 3)")
})
})
######
}
# Run the application
shinyApp(ui = ui, server = server)
您可以将其存储在反应值中:
global <- reactiveValues(ask = c(), logic = c())
observe({
Questions <- as.integer(input$Questions)
lapply(1:Questions, function(i) {
inputVal <- input[[paste0("Who", i)]]
if(!is.null(inputVal)){
global$logic[i] <- inputVal
}
inputValQ <- input[[paste0("Q", i)]]
if(!is.null(inputValQ)){
global$ask[i] <- inputValQ
}
})
})
这将为您生成以下代码示例: 作为副作用,如果输入被删除然后重新获取,这些值也会被存储。
library(shiny)
# Define UI
ui <- fluidPage(
# Application title
titlePanel("Identify A, B and C"),
sidebarLayout(
sidebarPanel(width = 5,
helpText("Present a statement and receive a response: 1 is a Knight who always tells the truth, 2 is a Knave who always lies, and 3 is a Normal who can do either."),
# Number of Questions
numericInput(inputId = "Questions", label = "Number of Questions",
value = 1, min = 1, max = 10, step = 1),
splitLayout(cellWidths = c("25%","70%"),
style = "border: 1px solid silver;",
cellArgs = list(style = "padding: 3px"),
uiOutput("textQuestions"), uiOutput("textQuestions2"))
),
mainPanel(
# Right hand side output
)
)
)
# Define server logic
server <- function(input, output) {
global <- reactiveValues(ask = c(), logic = c())
observe({
Questions <- as.integer(input$Questions)
lapply(1:Questions, function(i) {
inputVal <- input[[paste0("Who", i)]]
if(!is.null(inputVal)){
global$ask[i] <- inputVal
}
inputValQ <- input[[paste0("Q", i)]]
if(!is.null(inputValQ)){
global$logic[i] <- inputValQ
}
})
})
####### I don't want these to delete initially everytime??
output$textQuestions <- renderUI({
Questions <- as.integer(input$Questions)
lapply(1:Questions, function(i) {
textInput(inputId = paste0("Who", i), label = paste0(i, ". Ask:"), placeholder = "A", value = global$ask[i])
})
})
########
output$textQuestions2 <- renderUI({
Questions <- as.integer(input$Questions)
lapply(1:Questions, function(i) {
textInput(inputId = paste0("Q", i) , label = paste0("Logic:"), value = global$logic[i],
placeholder = "A == 1 & (B != 2 | C == 3)")
})
})
######
}
# Run the application
shinyApp(ui = ui, server = server)
看起来有人已经用 uiOutput
+renderUI
给了你答案,所以我要走另一条路:使用 insertUI
和 removeUI
.
我没有用 "number of questions" 的数字输入,而是用 "add question" 的按钮和 "remove question" 的按钮代替。我有一个变量来跟踪有多少问题。每按一次 "add question",我们就添加一行。当按下 "remove question" 时,我们删除最后一行。
代码如下:
library(shiny)
# Define UI
ui <- fluidPage(
# Application title
titlePanel("Identify A, B and C"),
sidebarLayout(
sidebarPanel(
width = 5,
helpText("Present a statement and receive a response: 1 is a Knight who always tells the truth, 2 is a Knave who always lies, and 3 is a Normal who can do either."),
# Buttons to add/remove a question
actionButton("add", "Add question"),
actionButton("remove", "Remove question"),
div(id = "questions",
style = "border: 1px solid silver;")
),
mainPanel(
# Right hand side output
)
)
)
# Define server logic
server <- function(input, output) {
# Keep track of the number of questions
values <- reactiveValues(num_questions = 0)
# Add a question
observeEvent(input$add, ignoreNULL = FALSE, {
values$num_questions <- values$num_questions + 1
num <- values$num_questions
insertUI(
selector = "#questions", where = "beforeEnd",
splitLayout(
cellWidths = c("25%","70%"),
cellArgs = list(style = "padding: 3px"),
id = paste0("question", num),
textInput(inputId = paste0("Who", num),
label = paste0(num, ". Ask:"),
placeholder = "A"),
textInput(inputId = paste0("Q", num) ,
label = paste0("Logic:"),
placeholder = "A == 1 & (B != 2 | C == 3)")
)
)
})
# Remove a question
observeEvent(input$remove, {
num <- values$num_questions
# Don't let the user remove the very first question
if (num == 1) {
return()
}
removeUI(selector = paste0("#question", num))
values$num_questions <- values$num_questions - 1
})
}
# Run the application
shinyApp(ui = ui, server = server)
编辑
OP 请求一种根据问题编号检索用户输入的方法。为此:
将以下内容添加到UI
numericInput("question_num", "Show question number", 1), textOutput("question")
将以下内容添加到服务器
get_question <- function(q) { paste( input[[paste0("Who", q)]], ":", input[[paste0("Q", q)]] ) } output$question <- renderText({ get_question(input$question_num) })