Skip to content

Conversation

@Tazovsky
Copy link

@Tazovsky Tazovsky commented Aug 8, 2025

Fix for Multiple shinyDirChoose Modal Issue

Problem Description

When using multiple shinyDirChoose buttons with different IDs in an R Shiny app, the modal where directories are selected does not close after clicking "Select". This issue occurs because:

  1. Each shinyDirChoose button creates its own modal with a unique ID
  2. The JavaScript event handlers use generic selectors (.sF-modalContainer) that can match multiple modals
  3. When multiple modals exist, the event handlers may target the wrong modal or cause conflicts

Root Cause

The issue was in the JavaScript code in inst/www/shinyFiles.js:

  1. No cleanup of existing modals: When creating a new modal, existing modals for the same button were not cleaned up
  2. Generic selectors in event handlers: The keydown handler and backdrop click handler used generic selectors that could match multiple modals
  3. Event handler conflicts: Multiple modals could interfere with each other's event handling

Solution

The fix includes several changes to inst/www/shinyFiles.js:

1. Modal Cleanup on Creation

Added cleanup of existing modals when creating new ones in all three modal creation functions:

// Clean up any existing modals for this button
var existingModal = $(button).data('modal');
if (existingModal) {
  removeFileChooser(button, existingModal);
}

This ensures that each button only has one active modal at a time.

2. Fixed Keydown Handler

Changed the keydown handler to work with multiple modals by finding the currently visible modal:

// Before (problematic)
if ($(".sF-modalContainer").is(":visible")) {
  var modalButton = $($(".sF-modalContainer").data('button'));
  // ...
}

// After (fixed)
var visibleModal = $(".sF-modalContainer:visible").first();
if (visibleModal.length > 0) {
  var modalButton = visibleModal.data('button');
  // ...
}

3. Fixed Backdrop Click Handler

Updated the backdrop click handler to work with the specific modal that was clicked:

// Before (problematic)
if (!$(e.target).closest('.modal-content').length > 0 && $("#sF-cancelButton").is(":visible")) {
  $("#sF-cancelButton").click();
}

// After (fixed)
if (!$(e.target).closest('.modal-content').length > 0 && $(this).find("#sF-cancelButton").is(":visible")) {
  $(this).find("#sF-cancelButton").click();
}

4. Fixed Escape Key Handler

Updated the escape key handler to work with the currently visible modal:

// Before (problematic)
if ($("#sF-cancelButton").is(":visible") && !$("div.sF-newDir").hasClass("open")) {
  $("#sF-cancelButton").click();
}

// After (fixed)
var visibleModal = $(".sF-modalContainer:visible").first();
if (visibleModal.length > 0 && visibleModal.find("#sF-cancelButton").is(":visible") && !visibleModal.find("div.sF-newDir").hasClass("open")) {
  visibleModal.find("#sF-cancelButton").click();
}

Testing

  1. Each modal opens and closes correctly
  2. The "Select" button properly closes the modal
  3. Multiple modals don't interfere with each other
  4. Keyboard shortcuts (Enter, Escape) work correctly

Files Modified

  • inst/www/shinyFiles.js: Fixed modal creation and event handlers

Impact

This fix resolves the issue where modals don't close after clicking "Select" when using multiple shinyDirChoose buttons. The fix is backward compatible and doesn't affect single modal usage.

This commit fixes the issue where modals don't close after clicking 'Select'
when using multiple shinyDirChoose buttons with different IDs in R Shiny apps.

Root Cause:
- Each shinyDirChoose button creates its own modal with unique ID
- JavaScript event handlers used generic selectors (.sF-modalContainer) that could match multiple modals
- When multiple modals exist, event handlers may target wrong modal or cause conflicts
- No cleanup of existing modals when creating new ones

Changes Made:

1. Added modal cleanup on creation:
   - Added cleanup code in createFileChooser(), createDirChooser(), createFileSaver()
   - Removes existing modals for same button before creating new one
   - Ensures each button only has one active modal at a time

2. Fixed keydown handler:
   - Changed from generic selector to finding currently visible modal
   - Uses .sF-modalContainer:visible.first() instead of .sF-modalContainer
   - Prevents conflicts between multiple modals

3. Fixed backdrop click handler:
   - Updated to work with specific modal that was clicked
   - Uses .find() instead of global selectors
   - Ensures correct modal is closed when clicking backdrop

4. Fixed escape key handler:
   - Updated to work with currently visible modal
   - Uses visibleModal.find() instead of global selectors
   - Ensures escape key closes correct modal

Impact:
- Resolves modal not closing issue with multiple shinyDirChoose buttons
- Backward compatible - doesn't affect single modal usage
- Improves reliability when using multiple file/directory choosers
Added Kamil Foltynski to the Authors@R field in DESCRIPTION with role 'ctb'
(contributor) to recognize the contribution to fixing the multiple modal issue
in shinyDirChoose functionality.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant