2015-07-14 3 views
7

У меня есть виджет textInput, и теперь, когда я начинаю вводить в виджет, shinyApp пытается оценить незавершенный контент в виджета textInput и приводит к многочисленным ошибкам. Я знаю, что добавление кнопки действий «Calculate» легко разрешит проблему. Тем не менее, у моего приложения не осталось места для еще одной кнопки. Итак, я хотел бы знать, есть ли способ, в котором виджет textInput будет «слушать» событие клавиатуры, например, когда пользователь нажимает «Enter?». Заранее спасибо!Блестящие ответы на ввод

+5

http://stackoverflow.com/questions/24973549/r-shiny-key-input-binding – Jimbo

+1

@EugeneChoe Отличная идея! Благодаря! –

+0

Рад, что мне было полезно! – Jimbo

ответ

0

В вашем случае проблема в реактивном программировании, и именно по этой причине вам нужно что-то для управления этой ситуацией. Моя рекомендация - использовать observer pattern или validate function.

  • шаблон Observer: блестящие реализующий паттерн наблюдатель, который полезно действовать, когда событие происходит в объекте (это может быть щелчок в кнопке, новое значение в качестве вклада ...) ,

  • Подтвердить функцию: функциональность этого процесса аналогична функции if/else. Действительно, есть need Что это такое, если нужно проверить параметр , если значения неправильные, появится сообщение об ошибке.

Чтобы узнать, как использовать шаблон наблюдения и функцию проверки, щелкните по предыдущей ссылке (на сайте Shiny все объяснено).

2

Вот приложение, которое я построил, и решает аналогичную проблему.

Идея состоит в том, чтобы прослушивать как нажатие кнопки, так и кнопку, и убедитесь, что они хорошо работают вместе. В вашем случае вы сможете сделать что-то еще проще, потому что вам не нужна кнопка.

Надеюсь, вам понравится.

library(shiny) 
# This is a demo app to test a key binding on an actionButton 
# Uncommenting the info item (on both UI and server) will display internal stuff 
runApp( 
    list(
    ############################################# 
    # UI 
    ############################################# 
    ui = bootstrapPage(
     textInput ("myinput", label = "Write something here"), 
     tags$script(' 
     $(document).on("keydown", function (e) { 
     Shiny.onInputChange("lastkeypresscode", e.keyCode); 
     }); 
     '), 
     actionButton("GO", "Lancer le matching !"), 
     # verbatimTextOutput("info"), 
     verbatimTextOutput("results") 
    ), 

    ############################################# 
    # SERVER 
    ############################################# 
    server = function(input, output, session) { 

     # There are state variables for the input text and GO button 
     curr.val <- "" # Corresponds to the current displayed input$myinput 
     curr.go <- 0 # Corresponds to the last known GO value (integer) 

     lastEvent <- reactive({ 
     # Is reactive to the following events 
     input$GO 
     input$lastkeypresscode 

     # Decide which action should be taken 
     if(input$GO > curr.go) { 
      # The user pushed the GO actionButton, so take action 
      action <- 1 
      curr.go <<- input$GO 
     } else if(input$lastkeypresscode == 13) { 
      # The user pressed the Enter key, so take action 
      action <- 1 
     } else { 
      # The user did anything else, so do nothing 
      action <- 0 
     } 

     return(action) 
     }) 

     output$results = renderPrint({ 
     if(lastEvent() == 1) { 
      curr.val <<- isolate(input$myinput) 
     } 
     curr.val 
     }) 

     # output$info = renderText({ 
     # paste(curr.val, curr.go, input$lastkeypresscode, sep = ", ") 
     # }) 
    } 
) 
) 
1

Я создал простое приложение в качестве примера, в котором пользователь может написать название города и после нажатия кнопки ENTER возвращает широта и долгота:

library(shiny) 
library(ggmap) 


runApp( 
    list(
    ############################################# 
    # UI 
    ############################################# 
ui = fluidPage(title = "City Search" , 
       position= "static-top", 
       tags$script(' $(document).on("keydown", function (e) { 
                Shiny.onInputChange("lastkeypresscode", e.keyCode); 
                }); 
                '), 
       # Search panel: 
       textInput("search_city", "" , placeholder= "City"), 
       verbatimTextOutput("results")), 

    ############################################# 
    # SERVER 
    ############################################# 
server = function(input, output, session) { 

    observe({ 
    if(!is.null(input$lastkeypresscode)) { 
     if(input$lastkeypresscode == 13){ 
     target_pos = geocode(input$search_city, messaging =FALSE) 
     LAT = target_pos$lat 
     LONG = target_pos$lon 
     if (is.null(input$search_city) || input$search_city == "") 
      return() 
     output$results = renderPrint({ 
      sprintf("Longitude: %s ---- Latitude: %s", LONG, LAT) 
     }) 
     } 
    } 
    }) 
} 
) 
) 

Обратите внимание, что для ловли ENTER ввода код равен 13, то есть input$lastkeypresscode == 13.

2

Очень хороший вопрос. Вот пример того, как я использую; это приложение показывает ggplot и пользователь дает название ggplot в текстовое поле - но изменения заголовка реагирует только тогда, когда «Return» нажата:

js <- ' 
$(document).on("keyup", function(e) { 
    if(e.keyCode == 13){ 
    Shiny.onInputChange("keyPressed", Math.random()); 
    } 
}); 
' 

shinyApp(
    ui = bootstrapPage(

    tags$script(js), 

    textInput("title", label = "Title"), 

    plotOutput("ggplot") 
), 

    server = function(input, output, session){ 

    Title <- reactiveVal() 

    observeEvent(input[["keyPressed"]], { 
     Title(input[["title"]]) 
    }) 

    output[["ggplot"]] <- renderPlot({ 
     ggplot(iris, aes(x=Sepal.Length, y=Sepal.Width)) + 
     geom_point() + 
     ggtitle(Title()) 
    }) 

    } 
) 

Пояснения:

Этот код Javascript:

$(document).on("keyup", function(e) { 
    if(e.keyCode == 13){ 
    Shiny.onInputChange("keyPressed", Math.random()); 
    } 
}); 

создает новый блестящий вход, а именно input$keyPressed, который получает случайное число, когда нажата клавиша «Return».

Затем я определяю реактивное значение, которое принимает значение input$title данное в текстовом поле пользователя, только когда input$keyPressed изменения:

Title <- reactiveVal() 

observeEvent(input[["keyPressed"]], { 
    Title(input[["title"]]) 
}) 

И, наконец, я передаю это реактивное значение ggtitle:

output[["ggplot"]] <- renderPlot({ 
    ggplot(iris, aes(x=Sepal.Length, y=Sepal.Width)) + 
    geom_point() + 
    ggtitle(Title()) 
}) 
Смежные вопросы