thomasp85 / shinyFiles

A shiny extension for server side file access
196 stars 47 forks source link

Trigger selection event #164

Closed sgvignali closed 2 years ago

sgvignali commented 2 years ago

Fix for #162

To test it use the following code:

library(shiny)
library(shinyFiles)
library(shinyjs)
library(fs)

ui <- fluidPage(
  useShinyjs(),
  headerPanel("Basic example"),
  sidebarLayout(
    sidebarPanel(
      shinyFilesButton(id = "file",
                       label = "File select",
                       title = "Please select a file",
                       multiple = FALSE,
                       viewtype = "detail"),
      tags$hr(),
      shinySaveButton(id = "save",
                      label = "Save file",
                      title = "Save file as...",
                      filetype = list(text = "txt"),
                      viewtype = "icon"),
    ),
    mainPanel(
      h4(id = "text"),
    )
  )
)

server <- function(input, output, session) {
  volumes <- c(Home = fs::path_home())

  shinyFileChoose(input,
                  id = "file",
                  roots = volumes,
                  session = session)
  shinyFileSave(input,
                "save",
                roots = volumes,
                session = session)

  shinyjs::runjs(
    "$('#file').on('selection', function(event, path)
                                  {$('#text').text('Files button clicked');})"
  )
  shinyjs::runjs(
    "$('#save').on('selection', function(event, path)
                                  {$('#text').text('File save: ' + path.name);})"
  )
}

shinyApp(ui = ui, server = server)
vnijs commented 2 years ago

Thanks for the PR @sgvignali. Can you explain why we would need an event to be triggered from clicking the select button? It currently works as intended without any modifications to the js code.

sgvignali commented 2 years ago

The event should be triggered when clicking on the save button not from the select button. Maybe I misunderstood the documentation and probably the following only applies to shinyFilesButton and shinyDirButton, but the description is a bit confusing:

If the shiny app uses custom Javascript it is possible to react to selections
directly from the javascript. Once a selection has been made, the button will
fire of the event 'selection' and pass the selection data along with the
event. To listen for this event you simple add:

$(button).on('selection', function(event, path) {
   // Do something with the paths here
})

in the same way a 'cancel' event is fired when a user dismisses a selection
box. In that case, no path is passed on.

Outside events the current selection is available as an object bound to the
button and can be accessed at any time:

// For a shinyFilesButton
$(button).data('files')

// For a shinyDirButton
$(button).data('directory')

// For a shinySaveButton
$(button).data('file')

In my case I need to run some javascript after the save button is clicked and I thought it would be great to have an event triggered on this action. Probably it should be a save and not a selection event though...

Of course, it is up to you whether or not you want to add this to the package. In case I can modify the PR and rename the triggered event to save

vnijs commented 2 years ago

OK. That helps me. Thanks @sgvignali. If there are additional "triggers" for selection and/or save that you think would be useful for those wanting to use custom javascript with shinyFiles, I'm fine with that as long as it does not affect the main functionality of the package in any way.

sgvignali commented 2 years ago

Sorry, the code I provided doesn't help much in understanding the purpose of the PR.

This is the only I have in mind since ShinyFileButton and ShinyDirButton already trigger an event. Do you want me to rename the event to save and update the documentation?

vnijs commented 2 years ago

That sounds great. Thanks @sgvignali

sgvignali commented 2 years ago

@vnijs I committed the changes, below the updated example:

library(shiny)
library(shinyFiles)
library(shinyjs)
library(fs)

ui <- fluidPage(
  useShinyjs(),
  headerPanel("Basic example"),
  sidebarLayout(
    sidebarPanel(
      shinyFilesButton(id = "file",
                       label = "File select",
                       title = "Please select a file",
                       multiple = FALSE,
                       viewtype = "detail"),
      tags$hr(),
      shinySaveButton(id = "save",
                      label = "Save file",
                      title = "Save file as...",
                      filetype = list(text = "txt"),
                      viewtype = "icon"),
    ),
    mainPanel(
      h4(id = "text"),
    )
  )
)

server <- function(input, output, session) {
  volumes <- c(Home = fs::path_home())

  shinyFileChoose(input,
                  id = "file",
                  roots = volumes,
                  session = session)
  shinyFileSave(input,
                "save",
                roots = volumes,
                session = session)

  shinyjs::runjs(
    "$('#file').on('selection', function(event, path)
                                  {$('#text').text('Files button clicked');})"
  )
  shinyjs::runjs(
    "$('#save').on('save', function(event, path)
                                  {$('#text').text('File save: ' + path.name);})"
  )
}

shinyApp(ui = ui, server = server)
vnijs commented 2 years ago

Thanks @sgvignali. Merged

sgvignali commented 2 years ago

Great, thank you @vnijs