我正在开发一个可以接受输入并显示它的闪亮应用程序。如何保持输入更多文本并保持进度?
setwd("G:/work/R_Prj/Learning-shiny")
library(shiny)
ui <- fluidPage(
titlePanel("TRY-1"),
sidebarLayout(
sidebarPanel(
textInput("txtInput", "Input to Display")
),
mainPanel(
paste("------------->"),
textOutput("txtOutput"),
textOutput("logg")
)
)
)
server <- shinyServer(function(input, output) {
logg <- NULL
output$txtOutput <- renderText({
if(nchar(input$txtInput)==0) {
txx <- paste(input$txtInput,"not yet input")
}else{
txx <- paste(input$txtInput,"<--------")
}
txx
})
output$logg <- renderText({
logg <- c(logg, input$txtInput)
})
})
shinyApp(ui = ui, server = server)
input$txtInput
作为接受文本输入的框,而output$txtOutput
作为接受文本的框。 output$logg
收集input$txtInput
。
如何收集输入的文本,打印(或txtOutput
)并将其保存以进行进一步处理,例如计数甚至保存日志?
我在这里可以想到两个问题。 1.如何判断输入结束,并标记为新记录? 2.如何记录和检索?保存每一个输入?然后返回第一个。
感谢您的建议。
答案 0 :(得分:2)
您可以将textInput
的值存储在reactiveValues
内,这些值在单击按钮时会更新。在下面的示例中,您将初始化一个空的data.frame
和一个计数器,这两个计数器在单击按钮时都会更新。所有输入都存储在data.frame
中。
如果您想在会话后存储此值以进行重用,则可以使用bookmarkButton
进行本地存储,也可以将这些值存储在SQL数据库或SQL Server数据库中。 永久存储的NoSQL数据库。
library(shiny)
ui <- fluidPage(
titlePanel("TRY-1"),
sidebarLayout(
sidebarPanel(
textInput("txtInput", "Input to Display"),
actionButton("store", "Store value in dataframe")
),
mainPanel(
tableOutput("table")
)
)
)
server <- shinyServer(function(input, output) {
rv <- reactiveValues(dfnew=data.frame(matrix(ncol = 2, nrow = 0)) ,count=1)
storedvalues <- observeEvent(input$store, {
if(nchar(input$txtInput) > 0) {
rv$dfnew <- rbind(rv$dfnew, df())
rv$count = rv$count + 1
} else {
}
})
df <- reactive({
data.frame(
id = rv$count,
value = input$txtInput
)
})
output$table <- renderTable({
rv$dfnew
})
})
shinyApp(ui = ui, server = server)
答案 1 :(得分:2)
除了现有的答案外,我还有一个可能对您感兴趣的原型。 它显示了如何动态记录闪亮应用程序中的输入更改。跟踪所有输入,而不必指定应该记录哪些输入。
代码可在此处找到:https://github.com/Timag/ShinyInputLog。
完整代码:
addListener <- '
function checkVariable() {
if (window.ip == true) {
sendToUI.setinputUpdate(["connected", "connected", window.ip]);
}
}
function Create(callback) {
var inputUpdate = false;
return {
getinputUpdate : function() { return inputUpdate; },
setinputUpdate : function(p) { inputUpdate = p; callback(inputUpdate);}
};
}
var sendToUI = Create(function(inputUpdate) {
if (inputUpdate) {
$.getJSON("//freegeoip.net/json/?callback=?", function(data) {
window.ip = JSON.stringify(data.ip, null, 2);
});
var val = inputUpdate[1].toString()
// dont allow other input types than the ones in UI-input to be logged
if(val.charAt(0) != "." && val != "logger"){
// datatableoutput gives input changes on itial start
if(val.substring(0,7) != "values_"){
Shiny.onInputChange("logger", [inputUpdate, window.ip]);
}
}
}
});
$(document).on("shiny:inputchanged", function(event) {
sendToUI.setinputUpdate([event.value, event.name]);
});
$(document).on("shiny:connected", function(event) {
$.getJSON("//freegeoip.net/json/?callback=?", function(data) {
window.ip = JSON.stringify(data.ip, null, 2);
});
setTimeout(checkVariable, 100);
});
$(document).on("shiny:disconnected", function(event) {
sendToUI.setinputUpdate(["disconnected", "disconnected"]);
});
'
if(!file.exists("log.csv")){
log <- data.frame(inputVal = "", inputId = "", UserIp = "", time = "")
write.table(log, "log/log.csv", sep = ";", append = TRUE, row.names = FALSE, col.names = TRUE)
}
#
library(shiny)
# Define UI for slider demo application
ui <- fluidPage(
tags$head(tags$script(HTML(addListener))),
# Application title
titlePanel("Input Logger"),
# Sidebar with sliders that demonstrate various available
# options
sidebarLayout(
sidebarPanel(
# Simple integer interval
sliderInput("integer", "Integer:",
min=0, max=1000, value=500),
# Decimal interval with step value
sliderInput("decimal", "Decimal:",
min = 0, max = 1, value = 0.5, step= 0.1),
# Specification of range within an interval
sliderInput("range", "Range:",
min = 1, max = 1000, value = c(200,500)),
# Provide a custom currency format for value display,
# with basic animation
sliderInput("format", "Custom Format:",
min = 0, max = 10000, value = 0, step = 2500,
pre = "$", sep = ",", animate=TRUE),
# Animation with custom interval (in ms) to control speed,
# plus looping
sliderInput("animation", "Looping Animation:", 1, 2000, 1,
step = 10, animate=
animationOptions(interval=300, loop=TRUE))
),
# Show a table summarizing the values entered
mainPanel(
dataTableOutput("values")
)
)
)
server <- function(input, output, session) {
observe({
input$logger
if(!is.null(input$logger)){
inputLog <- c(input$logger, as.character(Sys.time()))
# some input give double values - shorten to one string to fit it in the data table
if(length(inputLog) == 5) inputLog <- c(paste(input$logger[1:2], collapse = "-"), input$logger[3:4], as.character(Sys.time()))
# wait till file was updated
Sys.sleep(0.3)
write.table(as.data.frame(rbind(inputLog)), "log.csv", sep = ";", append = TRUE, row.names = FALSE, col.names = FALSE)
}
})
sliderValues <- reactive({
# Compose data frame
data.frame(
Name = c("Integer",
"Decimal",
"Range",
"Custom Format",
"Animation"),
Value = as.character(c(input$integer,
input$decimal,
paste(input$range, collapse=' '),
input$format,
input$animation)),
stringsAsFactors=FALSE)
})
output$values <- renderDataTable({
input$logger
data <- as.data.frame(read.table("log.csv", sep = ";", header = TRUE))
return(data[dim(data)[1]:1, ])
}, options = list(lengthMenu = c(10, 20, 50), pageLength = 10))
}
shinyApp(ui, server)
#runApp(shinyApp(ui, server), launch.browser = TRUE, display.mode = "showcase")