shiny: применить shinycustomerloader после нажатия кнопки actionButton

ФОН

У меня есть приложение, в котором пользователь выбирает имя файла из раскрывающегося меню (selectizeInput) и подтверждает выбор с помощью actionButton. Приложение отобразит результаты в формате DT::dataTableOutput.

ЗАДАЧА

Я хотел бы иметь возможность отображать экран загрузки (с использованием пакета shinydashboardloader), но только ПОСЛЕ того, как пользователь нажимает actionButton. Перед этим я хотел бы показать пустой экран. Кроме того, если пользователь хочет попробовать несколько файлов в одном сеансе, экран загрузки должен появляться каждый раз при нажатии кнопки actionButton и исчезать после загрузки набора данных.

ТЕКУЩЕЕ СОСТОЯНИЕ

В настоящее время, если я запускаю это приложение, кнопка загрузки появляется все время, даже до того, как пользователь выберет файл.

### ui.R
library(shiny)
library(shinydashboard)
library(DT)
library(shinycustomloader)

dashboardPage(
  dashboardHeader(),
  dashboardSidebar(

selectizeInput("file", "Select File",
               c("fileA", "fileB")), 

actionButton("submit", "Submit")
  ),
  dashboardBody(
    fluidRow(
      box(h2("My Data"),
      div(style = 'overflow-x: scroll', 
          withLoader(DT::dataTableOutput('mytable'),
                     type = "html",
                     loader = "loader1")),
      width = 12)

  )
  )
)


#### server.R
library(shiny)
library(shinydashboard)
library(DT)


shinyServer(function(input, output, session) {  

  file_name <- reactive({ 
req(input$file)
  })


  # When the Submit button is clicked, start the cleaning and matching 
  observeEvent(input$submit, {

## open chosen file 
#    open_file <- read_excel(paste0("input_files/", file_name()))

### + some processing that gives me matched_df

matched_df <- data.frame(A = c(1, 2, 3, 4),
                         B = c("A", "B", "C", "D"))

selected <- reactive({

  matched_df # + apply some filter

}) 



output$mytable = DT::renderDataTable({
  selected()
})


  })

})

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

ОБНОВИТЬ

Я применил conditionalPanel к datatable, но он работает только при первом нажатии кнопки «Отправить». Если в том же сеансе я изменю имя файла и снова нажму кнопку, загрузчик не появится. Есть идеи, как заставить его работать несколько раз за один сеанс?

  dashboardBody(
     fluidRow(
      box(h2("My Data"),
          conditionalPanel("input.submit==1",
          div(style = 'overflow-x: scroll', 
              withLoader(DT::dataTableOutput('mytable'),
                     type = "html",
                     loader = "loader1"))
      ),
      width = 12)

Любая помощь будет отличной, спасибо!


person Kasia Kulma    schedule 29.05.2018    source источник


Ответы (1)


1: Я не знаком с shinydashboardloader, но мне удалось добавить индикатор загрузки в свое приложение, используя пакет shinyjs для скрытия и отображения элементов с помощью CSS. Я бы добавил элементы страницы загрузки на главную страницу и обернул их функцией shinyjs::hidden, чтобы они были скрыты по умолчанию. Затем, когда пользователь нажимает кнопку действия, вызовите shinyjs::showElement, чтобы показать их, и shinyjs::hideElement, чтобы скрыть их после завершения загрузки.

UI:

shinyjs::hidden(div(id = 'loading',
           # PUT LOADING ELEMENTS HERE))

СЕРВЕР:

observeEvent(input$submit, {
    # Show element once submit button is pressed
    shinyjs::showElement(id = 'loading')

    # CODE TO MAKE DATA FRAME

    # Hide loading element when done
    shinyjs::hideElement(id = 'loading')
)

2: Что касается вашей проблемы с вашим редактированием, причина того, что ваша условная панель отображается только в первый раз, заключается в том, что значение actionButton увеличивается на единицу при каждом нажатии на нее. Таким образом, при первом щелчке он изменяется от 0 до 1; если вы щелкните по нему еще раз, он перейдет от 1 к 2 и так далее. Поскольку вы устанавливаете условие на input$select == 1, оно появится только в том случае, если кнопка была нажата ровно 1 раз.

Чтобы заставить его делать то, что вы хотите, вам нужно либо изменить условие на input$select > 1, чтобы оно отображалось до тех пор, пока кнопка была нажата один раз, либо добавить reactiveValue, который устанавливается в 1 при нажатии кнопки, а затем сбрасывается на 0 при выполнении другого условия (например, при завершении загрузки).

rv <- reactiveValues(loading = 0)

# When you click submit, show the loading screen
observeEvent(input$submit, {rv$loading <- 1})

# When you click LOAD, start loading, then hide the loading screen when finished
observeEvent(input$LOAD, {

    # CODE TO LOAD AND GENERATE DATA HERE

    rv$loading <- 0})
person divibisan    schedule 29.05.2018
comment
спасибо за действительно полезные советы! Все они имеют смысл, но ...! 1) Я не уверен, как выделить страницу загрузки как независимый элемент, поскольку shinycustomloader может применяться только к фактическому выводу. - person Kasia Kulma; 29.05.2018
comment
Проблемы, которые у меня возникают с пунктом 2, заключаются в том, что если я устанавливаю input.submit>=1, страница загрузки не появляется, когда я загружаю второй, третий и т. Д. Набор данных, вероятно, потому, что в dashboardBody уже есть предыдущий результат. Как я мог программно определить состояние «загрузка завершается», если бы я хотел использовать его для reactiveValue кондиционирования? - person Kasia Kulma; 29.05.2018
comment
спасибо за редактирование вашего ответа. Я все еще добираюсь до цели, но первое предложенное вами решение, скорее всего, сработает - мне нужно выкопать код CSS из shinydashboardloader и взять его оттуда. Спасибо! - person Kasia Kulma; 30.05.2018
comment
еще один вопрос по поводу вышеизложенного: если у меня есть css-скрипт для экрана загрузки, где и как мне включить его в shinyjs::hidden(div(id = 'loading', # PUT LOADING ELEMENTS HERE))? Я предположил, что он входит в dasboardBody (не вложен в fluidRow), а затем попытался обернуть его в includeCSS(), но безуспешно. - person Kasia Kulma; 31.05.2018
comment
Я бы сохранил весь CSS вместе и использовал селекторы, нацеленные на id для экрана загрузки, вместо того, чтобы иметь несколько связанных таблиц стилей. Если у вас проблемы с includeCSS, мне больше повезло, связав его вручную: tags$head(tags$link(rel = "stylesheet", type = "text/css", href = "styles.css")) - person divibisan; 31.05.2018