Applying DropZone bootstrap example under React JS
Asked Answered
S

2

5

I am trying to apply Dropzone bootstrap example under ReactJS as shown in the code below.

But for some reason, the Start Upload / Cancel Upload and progress bars are behaving in an inconsistent way.

Example 1: Progress bar shows endless progress even if I cancelled all files to be uploaded. Example 2: Start upload single file won't do anything.

Can someone please tell me what I am doing wrong/missing here and how can I make this work just like the example?

Note: Based on first reply if possible using Refs

import React from 'react';
import { connect } from 'react-redux';

@connect((state) => state)
export default class DZUploader extends React.Component {

  componentDidMount() {

  let previewNode = document.querySelector("#template");
  previewNode.id = "";

  let previewTemplate = previewNode.parentNode.innerHTML;
  previewNode.parentNode.removeChild(previewNode);

  let myDropzone = new Dropzone(document.body, {
    url: "/target-url", // Set the url
    paramName: "file", // The name that will be used to transfer the file
    maxFilesize: 2, // MB
    thumbnailWidth: 80,
    thumbnailHeight: 80,
    parallelUploads: 20,
    previewTemplate: previewTemplate,
    autoQueue: false,
    previewsContainer: "#previews",
    clickable: ".fileinput-button",
  });

  myDropzone.on('addedfile', function(file){
    console.log(file);
    file.previewElement.querySelector(".start").onclick = function() { myDropzone.enqueueFile(file); };
  });

  myDropzone.on('totaluploadprogress', function(progress){
    console.log(progress);
    document.querySelector("#total-progress .progress-bar").style.width = progress + "%";
  });

  myDropzone.on('sending', function(file){
    // Show the total progress bar when upload starts
    document.querySelector("#total-progress").style.opacity = "1";
    // And disable the start button
    file.previewElement.querySelector(".start").setAttribute("disabled", "disabled");
  });

  myDropzone.on('queuecomplete', function(progress){
    document.querySelector("#total-progress").style.opacity = "0";
  });

  document.querySelector("#actions .start").onclick = function() {
    myDropzone.enqueueFiles(myDropzone.getFilesWithStatus(Dropzone.ADDED));
  };
  document.querySelector("#actions .cancel").onclick = function() {
    myDropzone.removeAllFiles(true);
  };


  }

  render() {
    return (
      <div>

          <div id="actions" className="row">

              <div className="col-lg-7">
                <span className="btn btn-success fileinput-button dz-clickable">
                    <i className="glyphicon glyphicon-plus"></i>
                    <span>Add files...</span>
                </span>
                <button type="submit" className="btn btn-primary start">
                    <i className="glyphicon glyphicon-upload"></i>
                    <span>Start upload</span>
                </button>
                <button type="reset" className="btn btn-warning cancel">
                    <i className="glyphicon glyphicon-ban-circle"></i>
                    <span>Cancel upload</span>
                </button>
              </div>
              <div className="col-lg-5">
                <span className="fileupload-process">
                  <div id="total-progress" className="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0">
                    <div className="progress-bar progress-bar-success" data-dz-uploadprogress=""></div>
                  </div>
                </span>
              </div>

          </div>

          <div className="table table-striped" className="files" id="previews">
            <div id="template" className="file-row">
              <div>
                  <span className="preview"><img data-dz-thumbnail /></span>
              </div>
              <div>
                  <p className="name" data-dz-name></p>
                  <strong className="error text-danger" data-dz-errormessage></strong>
              </div>
              <div>
                  <p className="size" data-dz-size></p>
                  <div className="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0">
                    <div className="progress-bar progress-bar-success" data-dz-uploadprogress></div>
                  </div>
              </div>
              <div>
                <button className="btn btn-primary start">
                    <i className="glyphicon glyphicon-upload"></i>
                    <span>Start</span>
                </button>
                <button data-dz-remove className="btn btn-warning cancel">
                    <i className="glyphicon glyphicon-ban-circle"></i>
                    <span>Cancel</span>
                </button>
                <button data-dz-remove className="btn btn-danger delete">
                  <i className="glyphicon glyphicon-trash"></i>
                  <span>Delete</span>
                </button>
              </div>
            </div>
          </div>

      </div>
    );
  }
}
Sailfish answered 2/2, 2017 at 14:32 Comment(0)
C
7

3 things:

  1. By using componentDidMount lifecycle method doesn't mean that both $(JQuery) and dropzone are already loaded in the DOM

  2. Use React Refs instead of selectors so your components are consistent

  3. You should import the dropzone object with the import key and avoid the jquery dependency (import dropzone from 'dropzone').

Conclusion:

Avoid using Jquery when you don't need it, at least in this case.

As a conclusion to my suggestions your component should look like this:

import React from 'react';
import { connect } from 'react-redux';
import Dropzone from 'dropzone';

@connect((state) => state)
export default class DZUploader extends React.Component {

  constructor(props) {
    super(props);

    this.focus = this.focus.bind(this);
    this.onAddedfile = this.onAddedfile.bind(this);
    this.onTotaluploadprogress = this.onTotaluploadprogress.bind(this);
    this.onSending = this.onSending.bind(this);
    this.onQueuecomplete = this.onQueuecomplete.bind(this);
    this.onActionStartClick = this.onActionStartClick.bind(this);
    this.onActionCancelClick = this.onActionCancelClick.bind(this);
  }

  componentDidMount() {
    const previewNode = this.divTemplate;
    previewNode.id = "";

    const previewTemplate = previewNode.parentNode.innerHTML;
    previewNode.parentNode.removeChild(previewNode);

    const myDropzone = new Dropzone(document.body, {
      url: "/target-url", // Set the url
      paramName: "file", // The name that will be used to transfer the file
      maxFilesize: 2, // MB
      thumbnailWidth: 80,
      thumbnailHeight: 80,
      parallelUploads: 20,
      previewTemplate: previewTemplate,
      autoQueue: false,
      previewsContainer: "#previews",
      clickable: ".fileinput-button",
    });

    myDropzone.on('addedfile', onAddedfile);
    myDropzone.on('totaluploadprogress', onTotaluploadprogress);
    myDropzone.on('sending', onSending);
    myDropzone.on('queuecomplete', onQueuecomplete);

    this.actionStart.onclick = onActionStartClick;
    this.actionStart.onclick = onActionCancelClick;
  }

  onAddedfile(file) {
    console.log(file);
    file.previewElement.querySelector(".start").onclick = function() { myDropzone.enqueueFile(file); };
  }

  onTotaluploadprogress(progress) {
    console.log(progress);
    this.progressBar.style.width = progress + "%";
  }

  onSending(file) {
    // Show the total progress bar when upload starts
    this.totalProgress.style.opacity = "1";
    // And disable the start button
    file.previewElement.querySelector(".start").setAttribute("disabled", "disabled");
  }

  onQueuecomplete(progress) {
    this.totalProgress.style.opacity = "0";
  }

  onActionStartClick() {
    myDropzone.enqueueFiles(myDropzone.getFilesWithStatus(Dropzone.ADDED));
  }

  onActionCancelClick() {
    myDropzone.removeAllFiles(true);
  }
  render() {
    return (
      <div>

          <div id="actions" className="row">

              <div className="col-lg-7">
                <span className="btn btn-success fileinput-button dz-clickable">
                    <i className="glyphicon glyphicon-plus"></i>
                    <span>Add files...</span>
                </span>
                <button type="submit" className="btn btn-primary start" ref={(button) => { this.actionStart = button; }}>
                    <i className="glyphicon glyphicon-upload"></i>
                    <span>Start upload</span>
                </button>
                <button type="reset" className="btn btn-warning cancel" ref={(button) => { this.actionCancel = button; }}>
                    <i className="glyphicon glyphicon-ban-circle"></i>
                    <span>Cancel upload</span>
                </button>
              </div>
              <div className="col-lg-5">
                <span className="fileupload-process">
                  <div id="total-progress" ref={(div) => { this.totalProgress = div; }} className="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0">
                    <div className="progress-bar progress-bar-success" ref={(div) => { this.progressBar = div; }} data-dz-uploadprogress=""></div>
                  </div>
                </span>
              </div>

          </div>

          <div className="table table-striped" className="files" id="previews">
            <div id="template" ref={(div) => { this.divTemplate = div; }} className="file-row">
              <div>
                  <span className="preview"><img data-dz-thumbnail /></span>
              </div>
              <div>
                  <p className="name" data-dz-name></p>
                  <strong className="error text-danger" data-dz-errormessage></strong>
              </div>
              <div>
                  <p className="size" data-dz-size></p>
                  <div className="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0">
                    <div className="progress-bar progress-bar-success" data-dz-uploadprogress></div>
                  </div>
              </div>
              <div>
                <button className="btn btn-primary start">
                    <i className="glyphicon glyphicon-upload"></i>
                    <span>Start</span>
                </button>
                <button data-dz-remove className="btn btn-warning cancel">
                    <i className="glyphicon glyphicon-ban-circle"></i>
                    <span>Cancel</span>
                </button>
                <button data-dz-remove className="btn btn-danger delete">
                  <i className="glyphicon glyphicon-trash"></i>
                  <span>Delete</span>
                </button>
              </div>
            </div>
          </div>

      </div>
    );
  }
}
Complemental answered 2/2, 2017 at 15:12 Comment(2)
Thanks for your help, as of #3, I've already included dropzone as a dependency in the project bower.json, so it is already included. As of #2 would you mind please providing an example of applying Refs in my code, for example when trying to get the template div? I've viewed the documentation reference but can't manage to get it to work. ThanksSailfish
@Sailfish see the above example, it contains refs implementation. is quite simple.Complemental
T
2

The below is a demonstration of React + Dropzone + Relay usage.

Use Dropzone in your component.

<Dropzone style={{disply: 'none'}} disableClick={true}  ref="dropzone" onDrop={this.onDrop}/>

Implement onDrop function, here I'm doing a Relay mutation, if you are no using relay, then here should be making the post request to upload your file.

onDrop: function(files) {
  /*
  * TODO fire mutliple mutations triggars warnings
  */
  files.forEach((file)=> {
    Relay.Store.commitUpdate(
      new AddImageMutation({
        file,
        images: this.props.User,
      })
    );
  });
}

The above code can be found in relay-gallery

Live demo http://fanjin.computer/

Tautomerism answered 11/2, 2017 at 20:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.