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 към таблицата с данни, но работи само при първото натискане на бутона „Изпращане“. Ако в същата сесия променя името на файла и натисна отново бутона, товарачът няма да се появи. Някакви идеи как мога да го накарам да работи няколко пъти в една сесия?

  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(), но имах 0 успеха. - 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