2013-06-26 4 views
36

Я использую пакет Shiny GUI R. Я искал способ отображения сообщения типа «загрузка ...» после нажатия кнопки actionButton. Для выполнения этой функции требуется несколько минут, поэтому мне нужно как-то проинформировать пользователя о том, что кнопка фактически вызвала какое-то событие. Теперь код server.R выглядит следующим образом:R shiny: сообщение «loading ...» во время работы

DATA <- reactive({ 
    if(input$DownloadButton>0) { 
    RunDownload() 
    } else { 
    NULL 
    } 
}) 

output$Download <- renderText({ 
    if(NROW(DATA())>0) { 
    paste0(Sys.time(),": ",NROW(DATA()), " items downloaded") 
    } else { 
    '' 
    } 
}) 

actionButton() это функция, которая загружает данные из Интернета. input$DownloadButton - actionButton. Поэтому после нажатия кнопки пользователь ждет несколько минут и только затем видит сообщение о том, что загрузка прошла успешно. Я хотел бы показать сообщение «Загрузка ...» сразу после нажатия кнопки actionButton, а затем другое сообщение, например paste0(Sys.time(),": ",NROW(DATA()), " items downloaded"), когда выполнение завершено.

+0

Для упрощения вещей, я думаю, вам нужен индикатор выполнения, а в R есть много способов добавить его в функции. Можем ли мы иметь версию «RunDownload», чтобы увидеть, как добавить индикатор выполнения? – dickoa

+0

Мне не нужен индикатор выполнения, ну его можно назвать бинарным индикатором выполнения. Мне нужно показать 2 сообщения: один при запуске функции и один на конце функции. Я думаю, что забыл указать в теле сообщения, что я использую пакет Shiny, это не только R-код. Сейчас это исправит. – user1603038

ответ

28

Я уже использую более простой и надежный способ, чем тот, который я отправил раньше.

Сочетание

tags$style(type="text/css", " 
      #loadmessage { 
      position: fixed; 
      top: 0px; 
      left: 0px; 
      width: 100%; 
      padding: 5px 0px 5px 0px; 
      text-align: center; 
      font-weight: bold; 
      font-size: 100%; 
      color: #000000; 
      background-color: #CCFF66; 
      z-index: 105; 
      } 
    ") 

с

conditionalPanel(condition="$('html').hasClass('shiny-busy')", 
       tags$div("Loading...",id="loadmessage") 
) 

Пример:

runApp(list(
    ui = pageWithSidebar(
     headerPanel("Test"), 
     sidebarPanel(
      tags$head(tags$style(type="text/css", " 
      #loadmessage { 
       position: fixed; 
       top: 0px; 
       left: 0px; 
       width: 100%; 
       padding: 5px 0px 5px 0px; 
       text-align: center; 
       font-weight: bold; 
       font-size: 100%; 
       color: #000000; 
       background-color: #CCFF66; 
       z-index: 105; 
      } 
      ")), 
      numericInput('n', 'Number of obs', 100), 
      conditionalPanel(condition="$('html').hasClass('shiny-busy')", 
          tags$div("Loading...",id="loadmessage")) 
     ), 
     mainPanel(plotOutput('plot')) 
), 
    server = function(input, output) { 
    output$plot <- renderPlot({ Sys.sleep(2); hist(runif(input$n)) }) 
    } 
)) 

теги $ головы() не требуется, но это хорошая практика, чтобы сохранить все стили внутри head бирка.

+0

Можно ли сделать что-то подобное для таблиц 'renderDataTable' внутри страницы, на которые требуется некоторое время для загрузки? – 719016

+0

Люблю это решение, но мне сложно с ним работать с 'shinydashboard'. Любые идеи почему? В консоли разработчика я вижу, что условие запускается, но, несмотря на попытки множества разных местоположений и оболочек вокруг «conditionalPanel», я не могу получить сообщение, которое действительно отображается. – ClaytonJY

+0

В случае, если у кого-то есть тот же вопрос, что и я, я адаптировал этот способ обхода ошибок, чтобы получить более приятный внешний вид и более естественный для использования индикатор выполнения, который также работает на 'shinydashboard': https://github.com/rstudio/shiny/issues/609 – ClaytonJY

4

Я решил эту проблему, добавив следующий код sidebarPanel():

HTML('<script type="text/javascript"> 
     $(document).ready(function() { 
      $("#DownloadButton").click(function() { 
      $("#Download").text("Loading..."); 
      }); 
     }); 
     </script> 
') 
2

Я нашел решение, которое работает хорошо для меня. Я использую Bootstrap modal. Он отображается, когда выполнение функции начинается и снова скрывается, когда оно заканчивается.

< modalBusy - функция (идентификатор, название, ...) {

msgHandler = singleton(tags$head(tags$script('Shiny.addCustomMessageHandler("jsCode", 
              function(message) { 
               console.log(message) 
               eval(message.code); 
              });' 
              ) 
           ) 
        ) 

label_id = paste(id, "label", sep='-') 
modal_tag <- div(id=id, 
       class="modal hide fade", 
       "aria-hidden"=FALSE, 
       "aria-labelledby"=label_id, 
       "role"="dialog", 
       "tabindex"="-1", 
       "data-keyboard"=FALSE, 
       "data-backdrop"="static") 
header_tag <- div(class="modal-header", 
       h3(id=label_id, title)) 
body_tag <- div(class="modal-body", 
       Row(...)) 
footer_tag <- div(class="modal-footer") 
modal_tag <- tagAppendChildren(modal_tag, header_tag, body_tag, footer_tag) 
tagList(msgHandler, modal_tag) 
} 

Чтобы показать и скрыть его использовать функции

showModal <- function(id,session) { 
    session$sendCustomMessage(type="jsCode", 
          list(code= paste("$('#",id,"').modal('show')" 
              ,sep=""))) 
} 

hideModal <- function(id,session) { 
    session$sendCustomMessage(type="jsCode", 
          list(code= paste("$('#",id,"').modal('hide')" 
              ,sep=""))) 
} 

Вызов функции ShowModal перед тем ваша функция Call и функция hideModal впоследствии!

Надеюсь, это поможет.

Себ

+0

Я не могу заставить это работать. @Seb Можете ли вы поделиться рабочим примером.Спасибо – guna

3

Вы можете использовать ShinyJS: https://github.com/daattali/shinyjs

Когда actionButton нажата, вы можете легко переключаться компонентом текста, показывающим «загрузка ...», а когда расчет будет завершен, вы можете затем переключить этот компонент скрыты ,