本章节主要内容是如何实现包括确认,取消在内的用户反馈操作。
内容流程是先介绍validation
,用来让用户确认自己的输入。然后是介绍注意 notification
,用来编辑注意⚠️警告文。然后是progress bars
,这个是用来展示进度还有时间耗费。最后会介绍confirmation
和undo
的操作,用来确认和取消操作。
本章节主要是用shinyFeedback
包来实现以上的操作。
1 Validation验证
1.1 验证输入Input
具体操作大概分成两步。2 steps.
首先要在ui里加入useShinyFeedback()
。这一步的作用是自动设置需要的HTML和JAVA脚本。
ui <- fluidPage(
shinyFeedback::useShinyFeedback(),
numericInput("n", "n", value = 10),
textOutput("half")
)
然后需要在server端设置反馈信息。种类分成feedback, feedbackWarning, feedbackDanger, feedbackSuccess
。不管是哪一种包含三个参数信息。
-
inputId
: feedback对象的ID -
show
:有关是否要展示feedback信息的一个逻辑变量 -
text
: 需要展示的feedback信息
还有color
和icon
参数可以设置,详细信息可以参考帮助文件。
server <- function(input, output, session) {
half <- reactive({
even <- input$n %% 2 == 0
# inputID= "n"
# show= !even
# text= "Please select an even number"
shinyFeedback::feedbackWarning("n", !even, "Please select an even number")
input$n / 2
})
output$half <- renderText(half())
}
shinyApp(ui, server)
上面的代码虽然成功显示了警告文,但还是运行了代码给出了结果。理想的情况是不运行。可以用到之前提过的req()
函数。 之前文章里没有说明这是什么函数,其实是”require”的缩写。
server <- function(input, output, session) {
half <- reactive({
even <- input$n %% 2 == 0
shinyFeedback::feedbackWarning("n", !even, "Please select an even number")
req(even)
input$n / 2
})
output$half <- renderText(half())
}
1.2 用req()
取消代码执行
如果想实现在没有任何操作的情况下不显示任何信息,可以用req()
函数。
通常在下面的三个情况下可能会用到
-
textInput()
, 设置默认输入是value=””
,这个时候不会在有输入前跳出任何信息 -
selectInput()
,可以创建一个空白选项 -
fileInput()
,在有输入之前就是一个空白项
举个例子,如果不用req()
就会显示错误信息,虽然不会影响整体,但是不美观。
ui <- fluidPage(
selectInput("language", "Language", choices = c("", "English", "Maori")),
textInput("name", "Name"),
textOutput("greeting")
)
server <- function(input, output, session) {
greetings <- c(
English = "Hello",
Maori = "Kia ora"
)
output$greeting <- renderText({
paste0(greetings[[input$language]], " ", input$name, " !")
})
}
加入req()
以后就可以解决。 不符合逻辑要求的话所有下游的计算都会被取消。
server <- function(input, output, session) {
greetings <- c(
English = "Hello",
Maori = "Kia ora"
)
output$greeting <- renderText({
req(input$language, input$name)
paste0(greetings[[input$language]], " ", input$name, "!")
})
}
req()
有好几种用法,一种就是刚才的req(input$x)
,只有指定数值以后才执行接下来的代码。还有一种是req(input$a > 0)
添加逻辑判断函数。
1.3 req()
和验证
结合req()
和验证可以实现比较复杂的功能。比方说在输入错误的时候不要显示空白,而是把结果显示停留在之前的结果上。可以用到exists
函数来根据数据集是否存在的逻辑结果来激活feedbackDanger
,流程归纳一下就是如下:
输入datasets名字,req()
确认到输入以后执行操作,确认datasets名字存在,不存在的话发出警告文,并且cancel output。让结果停留在之前。
ui <- fluidPage(
shinyFeedback::useShinyFeedback(),
textInput("dataset", "Dataset name"),
tableOutput("data")
)
server <- function(input, output, session) {
data <- reactive({
req(input$dataset)
exists <- exists(input$dataset, "package:datasets")
shinyFeedback::feedbackDanger("dataset", !exists, "Unknown dataset")
req(exists, cancelOutput = TRUE)
get(input$dataset, "package:datasets")
})
output$data <- renderTable({
head(data())
})
}
get()
函数https://rdrr.io/r/base/get.html
1.4 Validate輸出
尽管之前介绍的shinyFeedback
看上去很有用,但是在面对多个错误的复杂条件的情况下也会显得无能为力,这时候就要用到validate()
函数了。
举个例子,我们需要计算一个输入值的平方,对数,开根号值。需要对数和开根号计算时对于小于0的输入值报错。
注意一下switch
的用法。
ui <- fluidPage(
numericInput("x", "x", value = 0),
selectInput("trans", "transformation",
choices = c("square", "log", "square-root")
),
textOutput("out")
)
server <- function(input, output, session) {
output$out <- renderText({
if (input$x < 0 && input$trans %in% c("log", "square-root")) {
validate("x can not be negative for this transformation")
}
switch(input$trans,
square = input$x ^ 2,
"square-root" = sqrt(input$x),
log = log(input$x)
)
})
}