闪亮的反应对象逻辑问题
Shiny reactive objects logic issue
我的目标是实现一个闪亮的应用程序,它向用户显示几个“问题”以及可能的答案列表,然后让用户选择一个答案并将其存储。每个问题都有一个用户可以覆盖的先前存储的答案。
我找不到用反应对象同时满足这两个约束的方法:
- 让用户select下一个问题,答案从先前存储的答案重新初始化
- 当用户 select 有新答案时存储当前问题的答案(并且仅在这种情况下)
下面是显示我当前尝试的简化代码(无数据,无 loading/writing)。在此版本中,问题是当 selected 新问题时,会立即写入上一个问题的 selected 答案。
library(shiny)
maxProblem=10
ui <- fluidPage(
titlePanel("Debugging test"),
fluidRow(
column(12,
verbatimTextOutput("nbProblems"),
uiOutput("ProblemSelection"),
uiOutput("answerSelection")
)
)
)
server <- function(input, output) {
output$ProblemSelection <- renderUI({
numericInput("ProblemSelectionNo",
"Select Problem no",
value = 1, min=1, max=maxProblem)
})
currentProblemData <- reactive({
print("calling loadCurrentProblemData")
if (!is.null(input$ProblemSelectionNo)) {
print("pretending to load data and previously stored answer for problem", input$ProblemSelectionNo)
list( choices=c(1,2,3), answer=1)
}
})
output$answerSelection <- renderUI({
l<-currentProblemData()
choicesList <- l$choices
names(choicesList) <- l$choices
radioButtons("answerInput", label = "Select answer",
choices = choicesList,
selected = l$answer)
})
writeChanges <- observe({
print('calling writeChanges')
l<-currentProblemData()
newAnswer <- input$answerInput
prevAnswer <- l$answer
if (!is.null(prevAnswer) && !is.null(newAnswer) && (newAnswer != prevAnswer)) {
print(paste('Pretending to write new answer :',newAnswer,'for problem', input$ProblemSelectionNo))
l$answer <- newAnswer
}
})
}
# Run the application
shinyApp(ui = ui, server = server)
这可能具有您正在寻找的功能。我做了一个可行的例子来尝试基于你所拥有的一些东西。
首先,我创建了一个默认列表choices_answer
,可以灵活地存储您的默认问题选择和答案。 reactiveValues
列表 lst
(rv$lst
) 将以此开头,然后随着选择新答案而改变以存储新响应。
当通过 numericInput
选择新问题时,radioButtons
会根据该问题的当前答案更新(使用 rv$lst
)。 Likewise, when a new answer is chosen (or answer is changed), the rv$lst
will be updated with the new answer for storage.
我还添加了输出 ListData
以显示当您使用单选按钮进行选择时答案的存储方式。
library(shiny)
maxProblem = 5
choices_answer = list()
for (i in seq_along(1:maxProblem)) {
choices_answer[[i]] <- list(
choices = c("1", "2", "3"),
answer = "1"
)
}
ui <- fluidPage(
titlePanel("Debugging test"),
fluidRow(
column(12,
numericInput("ProblemSelectionNo",
"Select Problem no",
value = 1, min = 1, max = maxProblem),
radioButtons("answerInput", label = "Select answer",
choices = choices_answer[[1]][["choices"]]),
verbatimTextOutput("ListData")
)
)
)
server <- function(input, output, session) {
rv <- reactiveValues(lst = choices_answer)
observeEvent(input$ProblemSelectionNo, {
updateRadioButtons(session, "answerInput",
choices = rv$lst[[input$ProblemSelectionNo]][["choices"]],
selected = rv$lst[[input$ProblemSelectionNo]][["answer"]])
})
observeEvent(input$answerInput, {
rv$lst[[input$ProblemSelectionNo]][["answer"]] <- input$answerInput
})
output$ListData <- renderPrint({rv$lst})
}
# Run the application
shinyApp(ui = ui, server = server)
我的目标是实现一个闪亮的应用程序,它向用户显示几个“问题”以及可能的答案列表,然后让用户选择一个答案并将其存储。每个问题都有一个用户可以覆盖的先前存储的答案。
我找不到用反应对象同时满足这两个约束的方法:
- 让用户select下一个问题,答案从先前存储的答案重新初始化
- 当用户 select 有新答案时存储当前问题的答案(并且仅在这种情况下)
下面是显示我当前尝试的简化代码(无数据,无 loading/writing)。在此版本中,问题是当 selected 新问题时,会立即写入上一个问题的 selected 答案。
library(shiny)
maxProblem=10
ui <- fluidPage(
titlePanel("Debugging test"),
fluidRow(
column(12,
verbatimTextOutput("nbProblems"),
uiOutput("ProblemSelection"),
uiOutput("answerSelection")
)
)
)
server <- function(input, output) {
output$ProblemSelection <- renderUI({
numericInput("ProblemSelectionNo",
"Select Problem no",
value = 1, min=1, max=maxProblem)
})
currentProblemData <- reactive({
print("calling loadCurrentProblemData")
if (!is.null(input$ProblemSelectionNo)) {
print("pretending to load data and previously stored answer for problem", input$ProblemSelectionNo)
list( choices=c(1,2,3), answer=1)
}
})
output$answerSelection <- renderUI({
l<-currentProblemData()
choicesList <- l$choices
names(choicesList) <- l$choices
radioButtons("answerInput", label = "Select answer",
choices = choicesList,
selected = l$answer)
})
writeChanges <- observe({
print('calling writeChanges')
l<-currentProblemData()
newAnswer <- input$answerInput
prevAnswer <- l$answer
if (!is.null(prevAnswer) && !is.null(newAnswer) && (newAnswer != prevAnswer)) {
print(paste('Pretending to write new answer :',newAnswer,'for problem', input$ProblemSelectionNo))
l$answer <- newAnswer
}
})
}
# Run the application
shinyApp(ui = ui, server = server)
这可能具有您正在寻找的功能。我做了一个可行的例子来尝试基于你所拥有的一些东西。
首先,我创建了一个默认列表choices_answer
,可以灵活地存储您的默认问题选择和答案。 reactiveValues
列表 lst
(rv$lst
) 将以此开头,然后随着选择新答案而改变以存储新响应。
当通过 numericInput
选择新问题时,radioButtons
会根据该问题的当前答案更新(使用 rv$lst
)。 Likewise, when a new answer is chosen (or answer is changed), the rv$lst
will be updated with the new answer for storage.
我还添加了输出 ListData
以显示当您使用单选按钮进行选择时答案的存储方式。
library(shiny)
maxProblem = 5
choices_answer = list()
for (i in seq_along(1:maxProblem)) {
choices_answer[[i]] <- list(
choices = c("1", "2", "3"),
answer = "1"
)
}
ui <- fluidPage(
titlePanel("Debugging test"),
fluidRow(
column(12,
numericInput("ProblemSelectionNo",
"Select Problem no",
value = 1, min = 1, max = maxProblem),
radioButtons("answerInput", label = "Select answer",
choices = choices_answer[[1]][["choices"]]),
verbatimTextOutput("ListData")
)
)
)
server <- function(input, output, session) {
rv <- reactiveValues(lst = choices_answer)
observeEvent(input$ProblemSelectionNo, {
updateRadioButtons(session, "answerInput",
choices = rv$lst[[input$ProblemSelectionNo]][["choices"]],
selected = rv$lst[[input$ProblemSelectionNo]][["answer"]])
})
observeEvent(input$answerInput, {
rv$lst[[input$ProblemSelectionNo]][["answer"]] <- input$answerInput
})
output$ListData <- renderPrint({rv$lst})
}
# Run the application
shinyApp(ui = ui, server = server)