blazor-docs/knowledge-base/upload-openselectfilesdialo...

4.1 KiB

title description type page_title slug position tags ticketid res_type
OpenSelectFilesDialog Doesn't Work in Safari Why the FileSelect and Upload OpenSelectFilesDialog method doesn't work in Safari due to browser security restrictions. troubleshooting FileSelect and Upload OpenSelectFilesDialog Method Doesn't Work in Safari upload-kb-openselectfilesdialog-safari telerik, blazor, fileselect, upload kb

Environment

Product FileSelect for Blazor,
Upload for Blazor
Browser Safari

Description

The OpenSelectFilesDialog method of the FileSelect and Upload components doesn't work in Safari. Normally, the browser should pop its native file selection dialog. In Safari, this browser dialog doesn't show when the application tries to open it programmatically via C#.

Possible Cause

The OpenSelectFilesDialog method is pretty simple. It uses JSInterop to call the click JavaScript method of the <input type="file" /> element inside the component HTML output.

Safari requires the file input dialog to open programmatically as a direct result of a user action. If the file input is clicked programmatically, this must happen in JavaScript code, which handles a user event.

JSInterop cannot be directly associated with a user action, due to its nature. A .NET method itself is not directly triggered by user action. For example, an @onclick Blazor handler will react to the click user event and call a .NET handler. However, the subsequent server-client JSInterop call that executes JavaScript code will no longer have relationship with the user action that started the whole sequence.

The following example demonstrates the described phenomenon without Telerik UI for Blazor components.

caption File Input Security in Safari

@inject IJSRuntime js

<p><input type="file" id="fileInput" /></p>

<p>
    <button onclick="openFileSelect()">Open File Dialog (JavaScript)</button>
    <button @onclick="@OpenFileSelectCS">Open File Dialog (JSInterop)</button>
</p>

@* Move JavaScript code to separate JS files in production apps *@
<script suppress-error="BL9992">//
function openFileSelect() {
    var input = document.querySelector("#fileInput");
    input.focus();
    input.click();
}
//</script>

@code {
    private async Task OpenFileSelectCS()
    {
        await js.InvokeVoidAsync("openFileSelect");
    }
}

Suggested Workarounds

The only possible way to open a FileSelect or Upload dialog programmatically is to use pure JavaScript and a user (client-side) event. The dialog opening call must have direct relationship to a user action, for example a button click. So, attach the event handler with JavaScript, instead of a Blazor directive such as @onclick.

caption Open FileSelect or Upload programmatically in Safari

@inject IJSRuntime js

<p>
    <TelerikButton Id="@ButtonId">Open File Dialog</TelerikButton>
</p>

<TelerikFileSelect Id="@FileSelectId" />

@* Move JavaScript code to separate JS files in production apps *@
<script suppress-error="BL9992">//
    function attachClickHandler(buttonId, fileInputId) {
        var button = document.getElementById(buttonId);
        var fileInput = document.getElementById(fileInputId);
        if (button && fileInput) {
            button.addEventListener("click", function(e) {
                fileInput.click();
            });
        }
    }
//</script>

@code {
    private string ButtonId { get; set; } = "button-id";

    private string FileSelectId { get; set; } = "fileselect-id";

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            await js.InvokeVoidAsync("attachClickHandler", ButtonId, FileSelectId);
        }
        await base.OnAfterRenderAsync(firstRender);
    }
}

See Also

  • [FileSelect Component]({%slug fileselect-overview%})
  • [Upload Component]({%slug upload-overview%})