DEV Community

Cover image for Drag & Drop Images with Preview using Stimulus Outlets
Rails Designer
Rails Designer

Posted on β€’ Originally published at railsdesigner.com

4

Drag & Drop Images with Preview using Stimulus Outlets

This articles was originally published on Rails Designer


In a previous article I explored a way to preview images before upload with Stimulus.

I know want to extend its functionality by adding a drag & drop. Along the way I am also using Stimulus outlets to tie the two functionalities together. Showcasing more advanced use of small Stimulus controllers.

I assume you walked through all the steps of the previous mentioned article.

Let's start with the HTML. It's using the other HTML with just a few attributes added.

<div data-controller="image-preview dropzone" data-action="dragover->dropzone#dragOver dragleave->dropzone#dragLeave drop->dropzone#drop">
  <img data-image-preview-target="canvas" hidden class="object-cover size-48">

  <input type="file" accept="image/*" data-image-preview-target="source" data-dropzone-target="input" data-action="image-preview#show" hidden>
</div>
Enter fullscreen mode Exit fullscreen mode

Let's create the dropzone_controller.js.

import { Controller } from "@hotwired/stimulus";

export default class extends Controller {
  static targets = ["input"];

  dragOver(event) {
    event.preventDefault();
  }

  dragLeave(event) {
    event.preventDefault();
  }

  drop(event) {
    event.preventDefault();

    this.#updateInputField(event.dataTransfer.files[0]);
  }
}
Enter fullscreen mode Exit fullscreen mode

All these methods do is preventing the default event when these actions are invoked. The drop() function also calls the private function this.#updateInputField(). Let's add it.

export default class extends Controller {
  // …

  // private
  #updateInputField(file) {
    const dataTransfer = new DataTransfer();

    dataTransfer.items.add(file);

    this.inputTarget.files = dataTransfer.files;
  }
  // …
}
Enter fullscreen mode Exit fullscreen mode

This will inject the dropped image into the inputTarget field. And just like that you can drag and drop images onto the element. 🀯

Preview images with outlets

An important part is missing though… the image isn't show which looks like a bug. Luckily with the image_preview_controller.js already done. This is a simple exercise.

First tweak the HTML by adding the following attributes:

<div data-controller="image-preview dropzone" data-dropzone-image-preview-outlet="#image-preview" data-action="dragover->dropzone#dragOver dragleave->dropzone#dragLeave drop->dropzone#drop" id="image-preview>
  <img data-image-preview-target="canvas" hidden class="object-cover size-48">

  <input type="file" accept="image/*" data-image-preview-target="source" data-dropzone-target="input" data-action="image-preview#show" hidden>
</div>
Enter fullscreen mode Exit fullscreen mode

Added:

  • data-dropzone-image-preview-outlet="#image-preview";
  • id="image-preview".

Now two lines are needed in the dropzone_controller.js.

export default class extends Controller {
  static outlets = ["image-preview"];
  // …

  drop(event) {
    // …

    this.imagePreviewOutlet.show();

    // …
  }

  // …
}
Enter fullscreen mode Exit fullscreen mode

Now when you drop an image it fires the show() function on the image_preview_controller.js. πŸ₯³

I like to use small Stimulus controllers like these that work great together.


Rails Designer has this Stimulus controller packaged with a few extras added. Get your copy today.

Image of Timescale

Timescale – the developer's data platform for modern apps, built on PostgreSQL

Timescale Cloud is PostgreSQL optimized for speed, scale, and performance. Over 3 million IoT, AI, crypto, and dev tool apps are powered by Timescale. Try it free today! No credit card required.

Try free

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

πŸ‘‹ Kindness is contagious

Please leave a ❀️ or a friendly comment on this post if you found it helpful!

Okay