проверять внутри downloadHandler - избегать создания файла - PullRequest
1 голос
/ 07 марта 2019

Фон

У меня есть reactive, который используется и для рендеринга вывода, но также и в downloadHandler. В этом reactive я использую validate, чтобы сообщить функции render*, если что-то не так. Тем не менее, это создает проблемы в downloadHandler. В приведенном ниже приложении, если вход не подтвержден, браузер показывает «Внутренняя ошибка сервера HTTP 500» (IE) или «Ошибка сервера - проблема» (Chrome) - ср. скриншоты.

Chrome Server Failed

IE HTTP 500

Желаемый результат

Я бы хотел сначала найти способ избежать такого поведения. Я прочитал Проверка внутри downloadHandler и Shiny: используйте validate () внутри downloadHandler , и оба рекомендуют скрыть / изменить кнопку загрузки в случае возникновения проблемы. Так как же будет выглядеть observer, который срабатывает всякий раз, когда reactive недопустим?

Примечание. не возможно изменить / адаптировать сам reactive, поскольку он инкапсулирован в модуле и модуль не имеет доступа к моему downloadHandler.

Код

library(shiny)

testUI <- function(id) {
  ns <- NS(id)
  numericInput(ns("n"), "n", 0, -3, 3)
}

test <- function(input, output, session) {
  r <- reactive({
    validate(need(input$n >= 0, "value is smaller than zero"))
    as.character(input$n)
  })
  list(reactive_i_cannot_change_because_the_code_does_not_belong_2_me = r)
}


ui <- fluidPage(testUI("my_module"), 
                downloadLink('downloadData', 'Download')
)

server <- function(input, output) {

  handler <- callModule(test, "my_module")

  output$downloadData <- downloadHandler(
    filename = function() {
      paste('data-', Sys.Date(), '.txt', sep='')
    },
    content = function(con) {
      writeLines(
        isolate(
           handler$reactive_i_cannot_change_because_the_code_does_not_belong_2_me()
        ), 
        con)
    }
  )

  observe({
    ## if i could react whenever handler$reactive...() is invalid
    ## I could simply hide the download button here
    ## Things that did not work: 
    ##   - tryCatch(handler$reactive...(), ...) 
    ##   - if (is.null(handler$reactive...())
  })
}

Ответы [ 2 ]

1 голос
/ 08 марта 2019

Я нашел решение.Хотя tryCatch не работал должным образом, я нашел решение с помощью try:

observe({
  res <- try(handler$reactive_i_cannot_change_because_the_code_does_not_belong_2_me(), TRUE)
  if ("try-error" %in% class(res)) {
    print("disable")
  }
})
1 голос
/ 07 марта 2019

Вы можете использовать функции show и hide из пакета shinyjs -

library(shiny)
library(shinyjs)

ui <- fluidPage(
  useShinyjs(),
  numericInput("n", "n", 0, -3, 3), 
  downloadLink('downloadData', 'Download')
)

server <- function(input, output, session) {
  r <- reactive({
    validate(need(input$n >= 0, "value is smaller than zero"))
    as.character(input$n)
  })

  output$downloadData <- downloadHandler(
    filename = function() {
      paste('data-', Sys.Date(), '.txt', sep='')
    },
    content = function(con) {
      writeLines(isolate(r()), con)
    }
  )

  observe({
    ## if i could react whenever r() is invalid
    ## I could simply hide the download button here
    ## tryCatch(r(), ...) did not work
    if(input$n < 0) {
      hide(id = "downloadData")
    } else {
      show(id = "downloadData")
    }
  })
}

shinyApp(ui, server)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...