Using a promise within an event

716 views Asked by At

I use flow.js (doc here) to upload documents on my website.

2 ways to upload something:

  • Through an 'upload' button
  • By drag'n drop

I would like to ask confirmation from the user if the file is drag'n droppped.

You can take a look at the code below:

 this.flow.on('fileAdded', (file, event) => {


        if (event.type == 'drop') // File has been dropped
        {
            if (!confirm("ok?"))
                this.flow.removeFile(file);
        }

    });

It works but it is not user friendly as you can see below:

enter image description here

Is there another solution? I thought about using promises and custom boxes, but so far I was not able to use a promise system in conjunction with this event handler (this.flow.on('fileAdded'...).

I don't think the fileAdded event is waiting for a promise.

2

There are 2 answers

3
Krystian Fiertek On

If you only wanna execute this.flow.removeFile(file) if confirm dialog fails there should be no problem. Just in your case take care with "this" as the context changes inside promise handler.

   this.flow.on('fileAdded', (file, event) =>{
        if (event.type == 'drop') // File has been dropped
        { 
            var self = this;
            confirm().then(function ok() {
                // nothing to do
            },function cancel() {
                self.flow.removeFile(file);
            });
        }

    });
5
Roamer-1888 On

The simplest way to generate an attractive, user friendly confirm dialog is to adopt something already written.

Here is something based on jQuery UI and a similar question answered here.

// static method of jQuery
(function($, $container) {
  $.confirm = function(question, title) {
    return $.Deferred(function(defer) {
      $container.html(question).dialog({
        'autoOpen': true,
        'modal': true,
        'title': title || 'Confirm',
        'buttons': {
          'Yes': defer.resolve,
          'No': defer.reject
        },
        'close': defer.reject
      });
    }).always(function() {
      $container.dialog('close');
    }).promise();
  }
}(jQuery, $('<div/>')));

Demo

You could write similar to mimic window.alert() and window.prompt()

Usage ...

jQuery.confirm(...) returns a promise, therefore you can write jQuery.confirm(...).then(...)

this.flow.on('fileAdded', (file, event) => {
    var that = this;
    if (event.type == 'drop') { // File has been dropped
        jQuery.confirm('Remove the file?').then(function() {
            that.flow.removeFile(file);
        }, function() {
            console.log('Removal of file not confirmed'); // or whatever you need to do when the action is not confirmed.
        });
    }
});

Don't forget, $.confirm(), as written above, is dependent on jQuery UI and its CSS file.

EDIT 1

The flow.js documentation isn't great but indicates that :

  • in a fileAdded handler, a file can be rejected by returning false.
  • a file can be added programmatically with Flow.addFile(file).

So with my jQuery.confirm(...) in place (and a bit of guesswork), here's something to try in the 'fileAdded' handler:

this.flow.on('fileAdded', (file, event) => {
    var flow = this.flow;
    if (event.type == 'drop') {
        jQuery.confirm('Remove the file?').then(function() {
            console.log('Removal of file confirmed');
            // flow.removeFile(file); // having returned false, this shouldn't be necessary.
        }, function() {
            console.log('Removal of file not confirmed');
            flow.addFile(file);
            // not sure if the queue will start/resume automatically; if not then try one of the following:
                // flow.upload(); 
                // flow.resume();
        });
        return false; // reject the file
    }
    return true;
});

Notes:

  1. I can't promise this is 100% correct. Comments indicate where the uncertainties lie. You may well need to run tests and be prepared to do some debugging.
  2. flow.addFile() will probably retrigger the 'fileAdded' event but your (event.type == 'drop') test should prevent you getting stuck in an infinite loop.