React-dnd: How can I get info about dragging files in canDrop method?

Created on 22 Nov 2016  ·  27Comments  ·  Source: react-dnd/react-dnd

I want to restrict allowed files extension and need to know what files user is dragging, but console throws warning: NativeDragSources.js:61 Browser doesn't allow reading "files" until the drop event. So what is the best way of checking file extension or dragging files count before dropping it on drop target?

pinned

Most helpful comment

Would it be possible to expose some information about the files via the event.dataTransfer object (e.g. types)? I realize that may not satisfy all use cases, but it would help at least some.

All 27 comments

Are you looking for not allowing drag on the Source OR to show not allowed on the Target based on a type ?

  1. to not allow drag, you should return false from canDrag in Source.
  2. to not allow drop, you should control using types on Target

@theTechie No, I'm loking for a way of reading file extension that I'm currently dragging.

All of the source and target methods get monitor as the second argument. (including canDrop)

You can use monitor.getItem() to get the currently dragged items.

Reference:

canDrop(props, monitor): Optional. Use it to specify whether the drop target is able to accept the item. If you want to always allow it, just omit this method. Specifying it is handy if you'd like to disable dropping based on some predicate over props or monitor.getItem(). Note: You may not call monitor.canDrop() inside this method.
you can use the monitor

It doesn't work for files

That's strange.
I believe you are dragging and dropping files from filesystem onto a Target ?

I have done a similar thing and it seems to be working for me. If you can share some code, we can probably see what's wrong.

Could you please show how you read file extension in canDrop method?

as i already mentioned above, monitor.getItem().files inside canDrop should give you an array of native File objects

Read my fist comment, when you read files in canDrop it throws error like I mentioned. Do you have working example of reading files in canDrop or you just refer to the documentation? Error says that i can't read files until drop event NativeDragSources.js:61 Browser doesn't allow reading "files" until the drop event

It's possible we are using two different versions and this restriction has been added later. I am using 2.1.4.

Ok, I will test the latest version and let you know if it works

I'm getting this, too, when trying to filter files in canDrop by MIME type. As soon as I call monitor.getItem().files it throws the above warning (Chrome 56.0.2924.87, react-dnd 2.2.4, react-dnd-html5-backend 2.2.4).

According to MDN my case, at least, could be accomplished using a property on event.dataTransfer, but as far as I can see, react-dnd doesn't expost that object or its information anywhere.

@theTechie

It's possible we are using two different versions and this restriction has been added later. I am using 2.1.4.

No, I use the same version. Also updated to the latest possible version (2.2.4) and getting the same error:

image

canDrop method looks like this:

canDrop: function (props, monitor) {      
        let files = monitor.getItem().files;
        console.log('Files: ', files);
        return true;
    }

How can it work on your side? Do you have working example?

I will share a working example shortly.
On Mon, 6 Mar 2017 at 4:12 PM, Andrey Karavaychik notifications@github.com
wrote:

@theTechie https://github.com/theTechie

It's possible we are using two different versions and this restriction has
been added later. I am using 2.1.4.

No, I use the same version. Also updated to the latest possible version
(2.2.4) and getting the same error:

[image: image]
https://cloud.githubusercontent.com/assets/710513/23606619/8acabe7a-0272-11e7-8db1-b1c88870cf92.png

canDrop method looks like this:

canDrop: function (props, monitor) {
let files = monitor.getItem().files;
console.log('Files: ', files);
return true;
}

How can it work on your side? Do you have working example?


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/react-dnd/react-dnd/issues/584#issuecomment-284361793,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AA_31panjV9Uo11jF63f2Pkx4FBKiV6Aks5ri-MtgaJpZM4K5hkG
.

>

Regards,
Gagan

@andrewQwer - really sorry!
i had a wrong memory of what i had implemented and it doesn't use monitor.getItem().files in canDrop, all i am doing is restricting the number of files which can be dropped by maintaining the file count once it's dropped.

sorry for misleading!

PS: i am looking into ways we can achieve this, will let you know if i am able to.

I don't think this will ever be possible. Looks like reading info on dragged items is restricted intentionally for security purpose.

http://stackoverflow.com/questions/25016442/how-to-distinguish-if-a-file-or-folder-is-being-dragged-prior-to-it-being-droppe

Would it be possible to expose some information about the files via the event.dataTransfer object (e.g. types)? I realize that may not satisfy all use cases, but it would help at least some.

This might be something to be added to the HTML5 backend, but it does seem possible to determine if a file fits an accepted set of mime types before the file/folder is dropped. Specifcally, react-dropzone does this when you hover the item over the dropzone, as can be seen in this example.

Any solution for this issue yet?

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

Not stale

I'm also looking for a way to allow dropping specific files, e.g.: images, video, like react-dropzone. Does anyone have a solution?

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

I have the issue too. It seems to be quite hardcoded in the "NativeDragSource.ts".

It creates a DragSource, however, for accessing the values it just adds a console-warning mentioning that the browser wouldn´t allow it.

However, the browser DOES allow it, it is just in protected mode and does not allow changing it or accessing the DATA ( of the files, but the items can with the files´ properties should be able to be enumerated. (like DropZone does).

Will try something and come back to you

@LeopoldLerch @darthtrevino I still cannot access to files list before I drop. I want to check the mime type of the file on hover and change the color of the border depending on if it's a valid format of the file. I am using canDrop method for useDrop hook. And it returns an array of files just when I drop. When I hover over drop zone I have an empty array

Thing is, the events, that the browser delivers, are as they are, we can´t change them. The browser gives access to the data only on dragstart. After that, all subsequent events are in protected mode, which means, you can´t access the data.

if you use the onHover method of useDrop, you will get empty metadata, as the browser does not allow you to access it on "dragenter". Even if you store the object in dragstart (or the collect-function), the browser will in the background clear the properties, as you do have a reference to the object, not a copy of it.

The only way to work around that, is to use the "collect" function. Here you can access the "items" or "files" of the item (depending on the browser you use, IE11 will never allow you to access them before ondrop).

however, you have to do all by yourself: validating and remembering it in eg. a useRef. For example

collect: monitor => {
            const item: DataTransfer = monitor.getItem();
            const isOver = monitor.isOver();
            let _canDrop: VerificationResult = null;
            if (item) {
                if (item.items) {
                    if (item.items.length > 0) {
                        draggedFilesValid.current = allFilesAccepted(
                            fromList<DataTransferItem>(item.items),
                            accept,
                            multiple,
                            maxSize,
                            minSize
                        )
                            ? VerificationResult.Valid
                            : VerificationResult.Invalid;
                    }
                }
            } else {
                draggedFilesValid.current = null;
            }

            if (isOver && item && item.files) {
                _canDrop = VerificationResult.Unknown;
                if (draggedFilesValid.current != null) {
                    _canDrop = disabled
                        ? VerificationResult.Invalid
                        : draggedFilesValid.current;
                }
            }

            return {
                isDragActive: item != null,
                canDrop: _canDrop
            };
        }

@LeopoldLerch
Thank you for the explanation! I will try this kind of workaround

Was this page helpful?
0 / 5 - 0 ratings