When to use

A common requirement is selecting multiple images and managing the selected list.

For example, you may have an image gallery or a set of images attached to a form. You can provide a button that opens the file manager to organize this set of files.

The Flmngr file manager not only supports picking multiple images in its dialog, but also allows you to modify the selection. Previously chosen images will be preselected when you open the file manager, making it easy to update the set.

How it works

You can call the file manager as shown in the select a single image sample and include preview generation like in the sample of getting image with preview, but with a few additional parameters.

First, set the isMultiple option to true to allow selecting multiple images.

To support reopening the dialog with previously selected images, use the list parameter. Pass all URLs of the previously selected images as a string array.

How to start using

Use this code in a custom application when you install the React file manager component or the JavaScript file manager package from NPM.

If your app doesn't use NPM at all, you can quickly install the file manager JS snippet instead.

These packages provide a powerful Flmngr API, which this and other code samples demonstrate.

Demo
Code
HTML
CSS
import {Flmngr} from "flmngr";

// This demo uses a script for animating showing full-screen image when user clicks on a preview (a-la LightBox)
import {LuminousGallery} from "https://cdn.skypack.dev/luminous-lightbox@2.4.0";

Flmngr.load({
  apiKey: "FLMN24RR1234123412341234",
  urlFileManager: 'https://fm.flmngr.com/fileManager',
  urlFiles: 'https://fm.flmngr.com/files',
  imageFormats: [
     {
        id: "preview",
        title: "Preview",
        suffix: "-preview",
        maxWidth: 250,
        maxHeight: 250
     }
  ]
}, {
  onFlmngrLoaded: () => {
    attachOnClickListenerToButton();
  }
});

function selectFiles() {
  
  // Collect URLs of images of existing gallery set
  let elsExistingImages = document.querySelectorAll(".image > img");
  let urls = [];
  for (let i=0; i<elsExistingImages.length; i++)
    urls.push(elsExistingImages.item(i).src);

  Flmngr.open({
    list: urls,
    isMultiple: true,
    acceptExtensions: ["png", "jpeg", "jpg", "webp", "gif"],
    createImageFormats: ["preview"],
    onFinish: (files) => {
      showSelectedImages(files);
    }
  });
}

function showSelectedImages(files) {
  let elImages = document.getElementById("images");
  elImages.innerHTML = "";
  
  let elP =  document.createElement("p");
  elP.textContent = files.length + " images selected";
  elImages.appendChild(elP);
  
  for (let file of files) {
    
    let filePreview = file.formats.find(file => file.format === "preview");
    let urlPreview = Flmngr.getNoCacheUrl(filePreview.url);
    let urlOriginal = Flmngr.getNoCacheUrl(file.url)
    
    let el = document.createElement("div");
    el.className = "image";
    elImages.appendChild(el);   
    
    let elImg = document.createElement("img");
    elImg.src = urlPreview;
    elImg.alt = "Image selected in Flmngr";
    elImg.setAttribute("data-src-original", urlOriginal);
    el.appendChild(elImg);
    
    let elP = document.createElement("p");
    elP.textContent = file.url;
    el.appendChild(elP);
    
  }        
  
  attachLightBoxToGallery();
}

function attachLightBoxToGallery() {

  let elsPreviews = document.querySelectorAll(".image > img");
  
  document.getElementById("hint").style.display = elsPreviews.length > 0 ? "block" : "none";

  elsPreviews.forEach(el => {
    if (!el.hasAttribute("data-src-original"))
      el.setAttribute("data-src-original", el.getAttribute("src"));
  });

  new LuminousGallery(
    elsPreviews,
    {
      "arrowNavigation": true
    },
    {
      "showCloseButton": true,
      "sourceAttribute": "data-src-original",
    }
  );
}

function attachOnClickListenerToButton() {
  let elBtn = document.getElementById("btn");
  
  // Style button as ready to be pressed
  elBtn.style.opacity = 1;
  elBtn.style.cursor = "pointer";
  let elLoading = document.getElementById("loading");
  elLoading.parentElement.removeChild(elLoading);
  
  // Add a listener for selecting files
  elBtn.addEventListener("click", () => {
    selectFiles();
  });
}
<h2 class="mb-3">Flmngr: Manage Image Gallery</h2>

<div id="btn" class="btn btn-primary btn-lg" style="opacity:0.2;cursor:default">Manage gallery</div>

<div id="loading" style="font-size:12px">Loading file manager...</div>

<p class="hint"><b>Hint</b>: After you have selected gallery images,<br/> you can re-manage the existing gallery.</p>

<h4 class="mt-5">Image gallery</h4>

<p id="hint" style="display:none" class="hint"><b>Hint</b>: the previews are clickable.</p>

<div id="images">
  <p>0 images selected</p>
</div>
body {
  padding: 20px;
  background-color: #F4F4F4;
}

h2 {
  font-weight: bold;
}

#images {
  
  .image {
    border: 1px solid #DDD;
    box-shadow: 5px 5px 0 0 #DDD;
    background-color: white;
    padding: 10px;
    display: inline-flex;
    flex-direction: column;
    margin: 0 25px 25px 0;
    
    img {
      max-height: 250px;
      cursor: pointer;
      border: 2px solid #007FFF;

      &:hover {
        border-color: orange;
      }
    }
    
    p {
      margin: 5px 0 0 0;
      font-size: 14px;
      color: #444;
    }
  }
  
}

.lum-img {
  cursor: zoom-out;
  max-width: 100vw !important;
  max-height: 100vh !important;
}

.lum-lightbox {
  z-index: 1000;
  cursor: zoom-out;
}

.lum-lightbox-inner img {
  margin: 0 auto;
}

.lum-lightbox-image-wrapper {
  display: flex;
  justify-content: center;
  align-items: center;
}

.lum-close-button {
  cursor: pointer;
}

.lum-lightbox-image-wrapper {
    background: rgba(0, 0, 0, 0.7);
}

.hint {
  color: #007FFF; 
  font-size:14px; 
  margin-top: 10px; 
  line-height: 16px;
}