I adapted the code from the tutorial here. It allows dragging or pasting files into a Blazor InputFile component. It works, however, unless I first click on the page with the mouse, I cannot use the keyboard shortcut control + v to paste a file. After I click the page with a mouse, the keyboard paste works as expected. It seems I must first “activate” the page with a mouse click.
I am blind and use a screen reader to navigate without a mouse. I asked a sighted person to try the page on their computer and they observed the same behavior, so I don’t think the screen reader is interfering with the process.
When composing a message with Gmail in the browser, I can paste files as attachments with control + v, without needing to first activate the page with a mouse click, so I think the behavior I hope for is possible.
Can someone suggest a way to make the code below work without a mouse?
[Upload.razor]
@page "/Upload"
<h2 style="text-align:center">Upload files</h2>
<div @ref="_fileDropContainer" class="file-drop-zone @_hoverClass" @ondragenter="OnDragEnter" @ondragleave="OnDragLeave" @ondragover="OnDragEnter">
<InputFile OnChange="@OnChange" @ref="_inputFile" />
<h1 style="text-align:center">Drag or paste files here</h1>
</div>
<div class="error-message-container">
<p>@_errorMessage</p>
</div>
@code {
ElementReference _fileDropContainer;
InputFile _inputFile;
IJSObjectReference _filePasteModule;
IJSObjectReference _filePasteFunctionReference;
string _hoverClass;
string _errorMessage;
override protected async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
_filePasteModule = await JS.InvokeAsync<IJSObjectReference>("import", "./js/filePaste.js");
_filePasteFunctionReference = await _filePasteModule.InvokeAsync<IJSObjectReference>("initializeFilePaste", _fileDropContainer, _inputFile.Element);
}
} //afterRender
async Task OnChange(InputFileChangeEventArgs args)
{
try
{
//omitted code for writing the file to disk
_hoverClass = "";
}
catch (Exception e)
{
// Exception handling omitted for brevity
}
this.StateHasChanged();
} // onChange
void OnDragEnter(DragEventArgs e) => _hoverClass = "hover";
void OnDragLeave(DragEventArgs e) => _hoverClass = "";
//Dispose method omitted
}
[filePaste.js]
export function initializeFilePaste(fileDropContainer, inputFile) {
function onPaste(e) {
inputFile.files = e.clipboardData.files;
const event = new Event('change', { bubbles: true });
inputFile.dispatchEvent(event);
}
fileDropContainer.addEventListener('paste', onPaste);
return {
dispose: () => {
fileDropContainer.removeEventListener('paste', onPaste);
}
}
}
Adding event listener to the document itself helped:
In your filePaste.js
:
//fileDropContainer.addEventListener('paste', onPaste);//change this to 👇
document.addEventListener('paste', onPaste);
You have to take care about the consequences. Mainly removing the event listener when you leave the page.