rshining: Как распечатать сообщение в приложении, если пользователь забыл загрузить файл?

Я создаю элементарное блестящее приложение. Сначала я создал фрейм данных «x» и сохранил его в своем рабочем каталоге:

x <- data.frame(a = 1:4, b = 2:5)
write.csv(x, 'x.csv', row.names = F)

В моем блеске я хотел бы:

  1. Загрузить файл 'x.csv'

  2. Нажмите мою кнопку действия «Нажмите здесь» и выполните несколько команд, нажав на нее.

  3. Получите сообщение, напечатанное в самом приложении Shiny: «Загрузите файл!» если я нажму на кнопку «Нажмите здесь», забыв сначала загрузить файл.

Мой код работает, но я не могу понять, как сделать так, чтобы мое сообщение отображалось.

Мой код:

library(shiny)

ui <- fluidPage(
  br(),
  # User should upload file x here:
  fileInput("file_x", label = h5("Upload file 'x'!")),
  br(),
  # Users clicks the button:
  actionButton("do_it", "Click Here"),
  br(),
  # Print last value of the button 'do_it':
  verbatimTextOutput("print_action")
)


server <- function(input, output, session) {

  observeEvent(input$do_it, {

    # Just a check of my button's actions:
    output$print_action <- renderPrint({input$do_it})

    # Validating the input - next 5 lines are not working:
    # validate(
    #   need(
    #     try(is.null(input$file_x), "Load a file!")
    #     )
    # )

    # Reading in the file:
    fileData <- reactive({
      infile <- input$file_x
      if (is.null(infile)) {
        return(NULL)
      }
      read.csv(infile$datapath)
    })
    x <- fileData()

    # Writing out the same file - but under a different name:
    filename <- paste0("x", input$do_it, ".csv")
    write.csv(x, file = filename, row.names = FALSE)

  })
}

shinyApp(ui, server)

person user3245256    schedule 30.01.2018    source источник
comment
Вы хотите отключить кнопку «Нажмите здесь», если резюме не загружено? или вы хотите, чтобы отображалось определенное сообщение, когда вы нажимаете здесь?   -  person Winicius Sabino    schedule 30.01.2018
comment
На самом деле, в этом случае вместо того, чтобы «скрывать» или «отключать» кнопку, я хотел бы напечатать сообщение. В моем ФАКТИЧЕСКОМ приложении я хочу, чтобы пользователь нажимал одну кнопку, которая проверяла бы все его входные данные (в моем случае это два разных фрейма данных, а затем их содержимое). И затем - всякий раз, когда что-то не так (когда файл не загружен или что-то внутри файлов не так) - я хочу вернуть сообщение или несколько сообщений пользователю.   -  person user3245256    schedule 30.01.2018


Ответы (1)


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

Обратите внимание, что я также немного изменил чтение csv. Плохая практика - устанавливать реактив внутри наблюдателя. В таких случаях лучше использовать reactiveVal, и обновите это с observer.

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

library(shiny)

ui <- fluidPage(
  br(),
  # User should upload file x here:
  fileInput("file_x", label = h5("Upload file 'x'!")),
  br(),
  # Users clicks the button:
  actionButton("do_it", "Click Here"),
  br(),
  br(),
  # Print last value of the button 'do_it':
  verbatimTextOutput("print_action")
)

server <- function(input, output, session) {

  observeEvent(input$do_it, {

    if(is.null(input$file_x))
    {
      # show pop-up ...
      showModal(modalDialog(
        title = "Oh no!",
        paste0("You have not uploaded a file, silly person!"),
        easyClose = TRUE,
        footer = NULL
      ))
      # ... or update the text
      my_text('Please upload a file.')
    }
    else
    {
      # Reading in the file:
      infile <- input$file_x
      if (is.null(infile)) {
        return(NULL)
      }
      x <- read.csv(infile$datapath)
      fileData(x) # set the reactiveVal called fileData to the file inputs.

      # Writing out the same file - but under a different name:
      filename <- paste0("x", input$do_it, ".csv")
      write.csv(x, file = filename, row.names = FALSE)
      my_text('Succes!')
    }
  })

  fileData <- reactiveVal()
  my_text <- reactiveVal('')
  output$print_action <- renderText({my_text()})
}

shinyApp(ui, server)
person Florian    schedule 30.01.2018
comment
Большое спасибо, Флориан! Это очень здорово. Могу я задать пару вопросов? Если мой пользователь должен загрузить 2 разных файла (через 2 разных входа) - можно ли расширить ваш код, используя elseif?: if(is.null(input$file_x)){ # показать всплывающее окно …, и остальные код } elseif {та же проверка, но для другого входного файла} else {остальная часть кода} Не могли бы вы еще раз объяснить, почему вы добавили fileData() в середине 'server.r? И в конце: fileData ‹- reactiveVal() my_text ‹- reactiveVal(’’) output$printaction ‹- renderText ({my_text()}) Спасибо! Большое спасибо! - person user3245256; 30.01.2018
comment
Расширение до двух файлов легко. Вам нужно всплывающее окно, когда любое из всплывающих окон имеет значение null; поэтому if(is.null(input$file_x)) должно быть if(is.null(input$file_x) |is.null(input$file_x2) ). x <- fileData() был не нужен, забыл убрать. Выполняя fileData(x), мы устанавливаем reactiveVal равным x, поэтому мы можем вызывать его содержимое из других реактивов и делать их зависимыми от него (например, отображать таблицу или график). Наконец, fileData <- reactiveVal() my_text <- reactiveVal('') инициирует реакцию, для получения дополнительной информации для тех, кто смотрит ссылку в моем ответе, потому что у меня не осталось символов;) - person Florian; 30.01.2018
comment
Спасибо, Флориан! - person user3245256; 30.01.2018
comment
Но что, если функция (подObservEvent) более сложная — например, читается в двух файлах, например, x и y? Тогда нужно написать: fileData(x) и fileData(y)? Но как мне получить доступ к каждому из них послесловия - вне реактивного? В настоящее время у нас есть: fileData ‹- reactiveVal() — но что, если есть два фрейма данных? - person user3245256; 30.01.2018
comment
Вы можете использовать reactiveValues вместо reactiveVal; то есть вы можете сделать fileData ‹- reactiveValues ​​(x = NA, y = NA) для хранения нескольких значений. Обратите внимание, что вызов и сохранение данных для них работает немного иначе, чем для reactiveVal, например. fileData$x <- 3 для хранения значений и fileData$x для извлечения. Надеюсь, это прояснит! - person Florian; 30.01.2018